phomemo 0.1.1 copy "phomemo: ^0.1.1" to clipboard
phomemo: ^0.1.1 copied to clipboard

A Flutter plugin to create information to send to phomemo printers.

example/lib/main.dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import 'bluetooth.dart';
import 'package:phomemo/phomemo.dart';
import 'package:image/image.dart' as img;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Phomemo Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  GlobalKey key = GlobalKey();
  late Bluetooth bluetooth;
  BluetoothOptions? bleOptions;

  bool isConnected = false;

  bool printing = false;
  String search = '';
  TextEditingController textController = TextEditingController();
  List<TextEditingController> sizeController = [TextEditingController(text: double.infinity.toString()),TextEditingController(text: '12.0')];
  Size labelSize = const Size(double.infinity,12);
  Uint8List? image;

  List<DropdownMenuItem<dynamic>> items = [];
  PhomemoPrinter printer = PhomemoPrinter.p12pro;
  List<bool> fixedLabel = [false,true];

  String showType = 'Example';

  @override
  void initState() {
    bluetooth = Bluetooth(
      onUpdate: _bleUpdate,
      names: ['P12Pro','D35','D30','Q155E2AQ1100400','Q199C0888888888','966df9e978cd'] /// 'Q--------------' Place the name of the m-type (m110,m120,m220) printer here. This is displayed on the front of the printer.
    );

    for(final printer in PhomemoPrinter.values){
      items.add(DropdownMenuItem(
        value: printer,
        child: Text(
          printer.name, 
          overflow: TextOverflow.ellipsis,
        )
      ));
    }
    super.initState();
  }
  @override
  void dispose() {
    bluetooth.dispose();
    super.dispose();
  }
  void _bleUpdate(BluetoothOptions options) {
    //setState(() {
      bleOptions = options;
    //});
    switch (options) {
      case BluetoothOptions.disconnected:
          setState(() {

          });
        break;
      case BluetoothOptions.connected:
        setState(() {

        });
        break;
      case BluetoothOptions.dataReceived:
        setState(() {

        });
        break;
      default:
        setState((){

        });
        break;
    }
  }
  Future<void> printPhomemo({Uint8List? image,String? name,Size? size})async{
    size ??= const Size(double.infinity,12);
    if(printing) return;
    printing = true;
    Phomemo label = Phomemo(
      send: bluetooth.write,
      packetSize: PhomemoPacketSize.p512,
    );
    img.Image? letter;
    if(showType == 'Custom'){
      letter = await textToImage(name,size);
    }
    else{
      letter = await PhomemoHelper.generateImageFromWidget(key);
    }

    await label.printLabel(
      [letter],
      printer: printer,
      spacing: 5,
      labelSize: labelSize,
      rotate: !PhomemoPrinter.isMType(printer) // do not rotate the image if using the m-type printer
    ).then((value){
      printing = false;
    });
  }

  Future<img.Image?> textToImage(String? text,Size size) async{
    img.Image? letter = text != null?await PhomemoHelper.generateImageFromText(
      TextSpan(
        text: text,
        style: const TextStyle(
          fontFamily: 'MuseoSans',
          fontSize: 34,
          color: Colors.black
        ),
      ),
      size: size*8,
    ):null;

    return letter;
  }

  Widget getWidget(){
    late Widget child;
    switch (printer) {
      case PhomemoPrinter.d35:
      case PhomemoPrinter.d30:
      case PhomemoPrinter.p12pro:
        child =  Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(5),
          ),
          alignment: Alignment.centerLeft,
          child: Row(
            children: [
              const Icon(Icons.add_photo_alternate_outlined),
              labelSize.width == double.infinity?const Text('This is an Example of the printer printing!'):labelSize.width > 35?const Text('Example!'):const Text('Ex!')
            ],
          ),
        );
        break;
      default:
        child = Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(10),
          ),
          alignment: Alignment.centerLeft,
          child: Container(
            width: double.infinity,
            margin: const EdgeInsets.all(10),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(5),
              border: Border.all(color: Colors.black,width: 2)
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Icon(Icons.add_photo_alternate_outlined),
                SizedBox(
                  height: PhomemoPrinter.isMType(printer)?10:20,
                ),
                Text(
                  PhomemoPrinter.isMType(printer)?'Example!':'This is an Example of the printer printing!',
                  textAlign: TextAlign.center,
                )
              ],
            ),
          ),
        );
    }

    return Container(
      width: (labelSize.width * 3)+30,
      height: (labelSize.height * 3)+30,
      margin: const EdgeInsets.only(top:5),
      padding: const EdgeInsets.fromLTRB(15, 15, 15, 15),
      color: Theme.of(context).focusColor,
      child: RepaintBoundary(
        key: key,
        child: child,
      )
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              bluetooth.deviceConnected()?'Type below the text you wish to print.':'Press floating action button to connect to a phomemo printer.',
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Container(
                  width: 120,
                  height:35,
                  padding: const EdgeInsets.only(left: 7.5,right: 7.5),
                  margin: const EdgeInsets.only(right: 20),
                  decoration: BoxDecoration(
                    color: Colors.purple[50],
                    borderRadius: const BorderRadius.all(Radius.circular(10)),
                  ),
                  child: DropdownButtonHideUnderline(
                    child: DropdownButton <dynamic>(
                      isExpanded: true,
                      items: items,
                      value: printer,
                      isDense: true,
                      onChanged: (d){
                        setState(() {
                          printer = d;

                          switch (printer) {
                            case PhomemoPrinter.d30:
                              labelSize = const Size(40, 12);
                              fixedLabel = [true,true];
                              break;
                            case PhomemoPrinter.d35:
                              labelSize = const Size(25, 12);
                              fixedLabel = [false,true];
                              break;
                            case PhomemoPrinter.p12pro:
                              labelSize = const Size(double.infinity, 12);
                              fixedLabel = [false,true];
                              break;
                            case PhomemoPrinter.m110:
                              labelSize = const Size(40,30);
                              fixedLabel = [false,false];
                              break;
                            case PhomemoPrinter.m120:
                            case PhomemoPrinter.m220:
                              labelSize = const Size(50, 80);
                              fixedLabel = [false,false];
                              break;
                            default:
                          }

                          sizeController[0].text = labelSize.width.toString();
                          sizeController[1].text = labelSize.height.toString();
                        });
                      },
                    ),
                  ),
                ),
                Container(
                  width: 120,
                  height:35,
                  padding: const EdgeInsets.only(left: 7.5,right: 7.5),
                  decoration: BoxDecoration(
                    color: Colors.purple[50],
                    borderRadius: const BorderRadius.all(Radius.circular(10)),
                  ),
                  child: DropdownButtonHideUnderline(
                    child: DropdownButton <String>(
                      isExpanded: true,
                      items: const [
                        DropdownMenuItem(
                          value: 'Example',
                          child: Text(
                            'Example', 
                            overflow: TextOverflow.ellipsis,
                          )
                        ),
                        DropdownMenuItem(
                          value: 'Custom',
                          child: Text(
                            'Custom', 
                            overflow: TextOverflow.ellipsis,
                          )
                        )
                      ],
                      value: showType,
                      isDense: true,
                      onChanged: (d){
                        setState(() {
                          showType = d!;
                        });
                      },
                    ),
                  ),
                ),
              ],
            ),
            showType == 'Custom'?Container(
              margin: const EdgeInsets.fromLTRB(10, 0, 10, 0),
              width: 320,
              height: 35,
              alignment: Alignment.center,
              child: TextField(
                keyboardType: TextInputType.multiline,
                maxLines: 1,
                autofocus: false,
                controller: textController,
                onChanged: (t)async {
                  image = img.encodePng((await textToImage(
                    textController.text,
                    labelSize
                  ))!);
                  setState(() {
                    
                  });
                },
                decoration: const InputDecoration(
                  isDense: true,
                  filled: true,
                  contentPadding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0),
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.all(
                      Radius.circular(10),
                    ),
                    borderSide: BorderSide(
                        width: 0, 
                        style: BorderStyle.none,
                    ),
                  ),
                  hintText: 'Text'
                ),
              )
            ):getWidget(),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Tape Size: ',
                ),
                Container(
                  margin: const EdgeInsets.fromLTRB(10, 0, 10, 0),
                  width: 80,
                  height: 35,
                  alignment: Alignment.center,
                  child: TextField(
                    readOnly: fixedLabel[0],
                    keyboardType: TextInputType.number,
                    inputFormatters: <TextInputFormatter>[
                        FilteringTextInputFormatter.digitsOnly
                    ],
                    maxLines: 1,
                    autofocus: false,
                    controller: sizeController[0],
                    onChanged: (t){
                      labelSize = Size(sizeController[0].text != ''?double.parse(sizeController[0].text):double.infinity, sizeController[1].text != ''?double.parse(sizeController[1].text):12);
                      setState(() {
                        
                      });
                    },
                    decoration: const InputDecoration(
                      isDense: true,
                      filled: true,
                      contentPadding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0),
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.all(
                          Radius.circular(10),
                        ),
                        borderSide: BorderSide(
                            width: 0, 
                            style: BorderStyle.none,
                        ),
                      ),
                      hintText: 'width'
                    ),
                  )
                ),
                Container(
                  margin: const EdgeInsets.fromLTRB(10, 0, 10, 0),
                  width: 80,
                  height: 35,
                  alignment: Alignment.center,
                  child: TextField(
                    readOnly: fixedLabel[1],
                    keyboardType: TextInputType.number,
                    inputFormatters: <TextInputFormatter>[
                        FilteringTextInputFormatter.digitsOnly
                    ],
                    maxLines: 1,
                    autofocus: false,
                    controller: sizeController[1],
                    onChanged: (t){
                      labelSize = Size(sizeController[0].text != ''?double.parse(sizeController[0].text):double.infinity, sizeController[1].text != ''?double.parse(sizeController[1].text):12);
                      setState(() {
                        
                      });
                    },
                    decoration: const InputDecoration(
                      isDense: true,
                      filled: true,
                      contentPadding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0),
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.all(
                          Radius.circular(10),
                        ),
                        borderSide: BorderSide(
                            width: 0, 
                            style: BorderStyle.none,
                        ),
                      ),
                      hintText: 'height'
                    ),
                  )
                ),
              ],
            ),
            if(showType == 'Custom')Container(
              width: (labelSize.width * 3)+30,
              height: (labelSize.height * 3)+30,
              padding: const EdgeInsets.fromLTRB(15, 15, 15, 15),
              color: Theme.of(context).focusColor,
              child: Container(
                width: (labelSize.width * 3),
                height: (labelSize.height * 3),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(10),
                  image: image == null?null:DecorationImage(image: MemoryImage(image!))
                ),
                alignment: Alignment.centerLeft,
              ),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async{
          if(bluetooth.deviceConnected()){
            labelSize = Size(sizeController[0].text != ''?double.parse(sizeController[0].text):double.infinity, sizeController[1].text != ''?double.parse(sizeController[1].text):12);
            if(!bluetooth.isStreaming && PhomemoPrinter.isM1Type(printer)){
              bluetooth.setNotification();
            }
            printPhomemo(
              name: textController.text,
              size: labelSize
            );
          }
          else if(!bluetooth.isScanning && bluetooth.device == null){
            if(
              ((Platform.isMacOS || Platform.isIOS) && await Permission.bluetooth.request().isGranted) 
              || (Platform.isAndroid && await Permission.bluetoothScan.request().isGranted && await Permission.bluetoothConnect.request().isGranted)
            ){
              bluetooth.startScan();
            }
          }
          else if(bluetooth.isScanning && bluetooth.device == null){
            bluetooth.stopScan();
          }
        },
        tooltip: bluetooth.deviceConnected()?'Print':'Search',
        child: Icon(bluetooth.deviceConnected()?Icons.print:((!bluetooth.isScanning && bluetooth.device == null)?Icons.bluetooth_disabled_rounded:Icons.bluetooth_audio)),
      ),
    );
  }
}
3
likes
150
points
462
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin to create information to send to phomemo printers.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, image

More

Packages that depend on phomemo