diff --git a/.github/actions/android/action.yml b/.github/actions/android/action.yml new file mode 100644 index 00000000..b2504b5f --- /dev/null +++ b/.github/actions/android/action.yml @@ -0,0 +1,59 @@ +name: "Android Workflow" + +inputs: + STORE_PASS: + description: 'Store Password' + required: false + default: '' + ALIAS: + description: 'Certificate Alias' + required: false + default: '' + KEY_PASS: + description: 'Key Password' + required: false + default: '' + VERSION_NAME: + description: 'Version Name to be used for build' + required: false + default: '1.0.0' + VERSION_CODE: + description: 'Version Code to be used for build' + required: true + default: '1' + +runs: + using: "composite" + steps: + - name: Set up Java + uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: 'adopt' + cache: 'gradle' + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + cache: true + flutter-version-file: pubspec.yaml + + - name: Build Android APK/AAB + shell: bash + env: + STORE_PASS: ${{ inputs.STORE_PASS }} + ALIAS: ${{ inputs.ALIAS }} + KEY_PASS: ${{ inputs.KEY_PASS }} + VERSION_NAME: ${{inputs.VERSION_NAME}} + VERSION_CODE: ${{inputs.VERSION_CODE}} + run: | + flutter build apk --debug --build-name $VERSION_NAME --build-number $VERSION_CODE + flutter build apk --build-name $VERSION_NAME --build-number $VERSION_CODE + flutter build appbundle --build-name $VERSION_NAME --build-number $VERSION_CODE + + - name: Store APK file + uses: actions/upload-artifact@v4 + with: + name: apk-files + path: | + build/app/outputs/flutter-apk/app-debug.apk \ No newline at end of file diff --git a/.github/actions/common/action.yml b/.github/actions/common/action.yml new file mode 100644 index 00000000..0cfa5bbd --- /dev/null +++ b/.github/actions/common/action.yml @@ -0,0 +1,26 @@ +name: "Common Workflow" + +runs: + using: "composite" + steps: + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + cache: true + flutter-version-file: pubspec.yaml + + - name: Fetch Flutter Dependencies + shell: bash + run: flutter pub get + + - name: Validate Code Format + shell: bash + run: dart format --output=none --set-exit-if-changed . + + - name: Analyze Code + shell: bash + run: flutter analyze --no-fatal-infos + + - name: Run tests + shell: bash + run: flutter test diff --git a/.github/actions/ios/action.yml b/.github/actions/ios/action.yml new file mode 100644 index 00000000..ed499341 --- /dev/null +++ b/.github/actions/ios/action.yml @@ -0,0 +1,45 @@ +name: "iOS Workflow" + +inputs: + VERSION_NAME: + description: 'Version Name to be used for build' + required: false + default: '1.0.0' + VERSION_CODE: + description: 'Version Code to be used for build' + required: true + default: '1' + +runs: + using: "composite" + steps: + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + cache: true + flutter-version-file: pubspec.yaml + + - name: Update Podfile + shell: bash + run: | + cd ./iOS + flutter pub get + pod install --repo-update + + - name: Build iOS IPA (No Code Signing for PRs) + if: ${{ github.event_name == 'pull_request' }} + shell: bash + env: + VERSION_NAME: ${{ inputs.VERSION_NAME }} + VERSION_CODE: ${{ inputs.VERSION_CODE }} + run: | + flutter build ipa --no-codesign --build-name $VERSION_NAME --build-number $VERSION_CODE + + - name: Build iOS IPA (With Code Signing) + if: ${{ github.event_name == 'push' }} + shell: bash + env: + VERSION_NAME: ${{ inputs.VERSION_NAME }} + VERSION_CODE: ${{ inputs.VERSION_CODE }} + run: | + flutter build ipa --build-name $VERSION_NAME --build-number $VERSION_CODE diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 00000000..8b1f11ce --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,36 @@ +name: Magic Epaper PR CI + +on: + pull_request: + branches: + - main + +jobs: + common: + name: Common Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Common Workflow + uses: ./.github/actions/common + + android: + name: Android Flutter Build + needs: common + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Android Workflow + uses: ./.github/actions/android + + ios: + name: iOS Flutter Build + needs: common + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + + - name: iOS Workflow + uses: ./.github/actions/ios \ No newline at end of file diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 00000000..853eb88e --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,198 @@ +name: Magic Epaper Push CI + +on: + push: + branches: + - main + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ANDROID_EMULATOR_API: 34 + ANDROID_EMULATOR_ARCH: x86_64 + IPHONE_DEVICE_MODEL: iPhone 16 Pro Max + IPAD_DEVICE_MODEL: iPad Pro 13-inch (M4) + +jobs: + common: + name: Common Build + runs-on: ubuntu-latest + outputs: + VERSION_NAME: ${{ steps.flutter-version.outputs.VERSION_NAME }} + VERSION_CODE: ${{ steps.flutter-version.outputs.VERSION_CODE }} + steps: + - name: Checkout main + uses: actions/checkout@v4 + + - name: Common Workflow + uses: ./.github/actions/common + + - name: Hydrate and Update Version + id: flutter-version + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + # Get commit message + commit_message=$(git log -1 --pretty=format:"%s") + + git clone --branch=version https://${{ github.repository_owner }}:${{ github.token }}@github.com/${{ github.repository }} version + cd version + + # Read and increment version name + IFS='.' read -r major minor patch < versionName.txt + + if [[ "$commit_message" =~ ^feat: ]]; then + next_minor=$((minor + 1)) + next_patch=0 + else + next_minor=$((minor)) + next_patch=$((patch + 1)) + fi + next_version_name="$major.$next_minor.$next_patch" + echo "VERSION_NAME=$next_version_name" >> $GITHUB_OUTPUT + echo "$next_version_name" > versionName.txt + + # Read and increment version code + read -r version_code < versionCode.txt + + new_version_code=$((version_code + 1)) + echo "VERSION_CODE=$new_version_code" >> $GITHUB_OUTPUT + echo "$new_version_code" > versionCode.txt + + # Force push to version branch + git checkout --orphan temporary + git add --all . + git commit -am "[Auto] Update versionName: $next_version_name & versionCode: $new_version_code ($(date +%Y-%m-%d.%H:%M:%S))" + git branch -D version + git branch -m version + git push --force origin version + + android: + name: Android Flutter Build + needs: common + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Prepare Build Keys + if: ${{ github.repository == 'fossasia/magic-epaper-app' }} + env: + ENCRYPTED_F10B5E0E5262_IV: ${{ secrets.ENCRYPTED_F10B5E0E5262_IV }} + ENCRYPTED_F10B5E0E5262_KEY: ${{ secrets.ENCRYPTED_F10B5E0E5262_KEY }} + run: | + bash scripts/prep-android-key.sh + + - name: Android Workflow + uses: ./.github/actions/android + with: + STORE_PASS: ${{ secrets.STORE_PASS }} + ALIAS: ${{ secrets.ALIAS }} + KEY_PASS: ${{ secrets.KEY_PASS }} + VERSION_NAME: ${{needs.common.outputs.VERSION_NAME}} + VERSION_CODE: ${{needs.common.outputs.VERSION_CODE}} + + - name: Upload APK + uses: actions/upload-artifact@v4 + with: + name: APK Generated + path: build/app/outputs/flutter-apk + + - name: Upload AAB Release + uses: actions/upload-artifact@v4 + with: + name: AAB Generated + path: build/app/outputs/bundle + + - name: Upload APK/AAB to apk branch + if: ${{ github.repository == 'fossasia/magic-epaper-app' }} + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + git clone --branch=apk https://${{ github.repository_owner }}:${{ github.token }}@github.com/${{ github.repository }} apk + cd apk + + branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} + + echo "Removing previous files from branch" + + rm -rf magic-epaper-$branch* + + ls + + echo "Copying new build files" + + find ../build/app/outputs/flutter-apk -type f \( -name '*.apk' -o -name '*.aab' \) -exec cp -v {} . \; + find ../build/app/outputs/bundle -type f \( -name '*.apk' -o -name '*.aab' \) -exec cp -v {} . \; + + ls + + echo "Renaming new build files" + + for file in app*; do + mv $file magic-epaper-$branch-${file#*-} + done + + ls + + echo "Pushing to apk branch" + + git checkout --orphan temporary + git add --all . + git commit -am "[Auto] Update APK/AAB's from $branch ($(date +%Y-%m-%d.%H:%M:%S))" + git branch -D apk + git branch -m apk + git push --force origin apk + + - name: Push app in open testing track + if: ${{ github.repository == 'fossasia/magic-epaper-app' }} + run: | + cd ./android + git clone --branch=fastlane-android --depth=1 https://${{ github.repository_owner }}:${{ github.token }}@github.com/${{ github.repository }} fastlane + fastlane uploadToOpenTesting + if [[ $? -ne 0 ]]; then + exit 1 + fi + + ios: + name: iOS Flutter Build + needs: common + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + + - name: Prepare Build Keys + if: ${{ github.repository == 'fossasia/magic-epaper-app' }} + env: + ENCRYPTED_IOS_IV: ${{ secrets.ENCRYPTED_IOS_IV }} + ENCRYPTED_IOS_KEY: ${{ secrets.ENCRYPTED_IOS_KEY }} + run: | + bash scripts/prep-ios-key.sh + + - name: Setup Certs + if: ${{ github.repository == 'fossasia/magic-epaper-app' }} + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }} + run: | + cd ./iOS + git clone --branch=fastlane-ios --depth=1 https://${{ github.repository_owner }}:${{ github.token }}@github.com/${{ github.repository }} fastlane + fastlane setupCertificates + if [[ $? -ne 0 ]]; then + exit 1 + fi + + - name: iOS Workflow + uses: ./.github/actions/ios + with: + VERSION_NAME: ${{needs.common.outputs.VERSION_NAME}} + VERSION_CODE: ${{needs.common.outputs.VERSION_CODE}} + + - name: Push app to testflight + if: ${{ github.repository == 'fossasia/magic-epaper-app' }} + run: | + cd ./iOS + fastlane uploadToBeta + if [[ $? -ne 0 ]]; then + exit 1 + fi diff --git a/lib/main.dart b/lib/main.dart index d98884d0..c712efac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,12 +5,9 @@ import 'package:provider/provider.dart'; import 'package:magic_epaper_app/view/home_screen.dart'; void main() { - runApp(MultiProvider( - providers: [ - ChangeNotifierProvider(create: (context) => ImageLoader()), - ], - child: const MyApp() - )); + runApp(MultiProvider(providers: [ + ChangeNotifierProvider(create: (context) => ImageLoader()), + ], child: const MyApp())); } class MyApp extends StatelessWidget { @@ -19,12 +16,12 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: 'Magic Epaper', - theme: ThemeData( - useMaterial3: true, - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange), - ), - home: const SelectDisplay(), - ); + title: 'Magic Epaper', + theme: ThemeData( + useMaterial3: true, + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange), + ), + home: const SelectDisplay(), + ); } -} \ No newline at end of file +} diff --git a/lib/provider/image_loader.dart b/lib/provider/image_loader.dart index 01f1aa91..d0fbd4fc 100644 --- a/lib/provider/image_loader.dart +++ b/lib/provider/image_loader.dart @@ -14,7 +14,8 @@ class ImageLoader extends ChangeNotifier { final croppedFile = await ImageCropper().cropImage( sourcePath: file.path, - aspectRatio: CropAspectRatio(ratioX: width.toDouble(), ratioY: height.toDouble()), + aspectRatio: + CropAspectRatio(ratioX: width.toDouble(), ratioY: height.toDouble()), ); if (croppedFile == null) return; @@ -23,4 +24,4 @@ class ImageLoader extends ChangeNotifier { notifyListeners(); } -} \ No newline at end of file +} diff --git a/lib/util/epd/driver/driver.dart b/lib/util/epd/driver/driver.dart index e3cacd44..16ef656d 100644 --- a/lib/util/epd/driver/driver.dart +++ b/lib/util/epd/driver/driver.dart @@ -1,4 +1,4 @@ abstract class Driver { List get transmissionLines; int get refresh; -} \ No newline at end of file +} diff --git a/lib/util/epd/edp.dart b/lib/util/epd/edp.dart index 6c610c42..bce45d8e 100644 --- a/lib/util/epd/edp.dart +++ b/lib/util/epd/edp.dart @@ -11,18 +11,24 @@ abstract class Epd { String get description; List get colors; Driver get controller; - + Uint8List _extractEpaperColorFrame(Color color, img.Image orgImage) { final image = ImageProcessing.extract(color, orgImage); - final colorPixel = img.ColorRgb8(color.red, color.green, color.blue); + final red = (color.r * 255).toInt(); + final green = (color.g * 255).toInt(); + final blue = (color.b * 255).toInt(); + final colorPixel = img.ColorRgb8(red, green, blue); List bytes = List.empty(growable: true); - int j=0; + int j = 0; int byte = 0; - + for (final pixel in image) { - var bin = pixel.rNormalized - colorPixel.rNormalized - + pixel.gNormalized - colorPixel.gNormalized - + pixel.bNormalized - colorPixel.bNormalized; + var bin = pixel.rNormalized - + colorPixel.rNormalized + + pixel.gNormalized - + colorPixel.gNormalized + + pixel.bNormalized - + colorPixel.bNormalized; if (bin > 0.5) { byte |= 0x80 >> j; @@ -42,10 +48,10 @@ abstract class Epd { List extractEpaperColorFrames(img.Image orgImage) { final retList = []; for (final c in colors) { - if(c == Colors.white) continue; // skip white + if (c == Colors.white) continue; // skip white retList.add(_extractEpaperColorFrame(c, orgImage)); } return retList; } // TODO: howToAdjust ??? -} \ No newline at end of file +} diff --git a/lib/util/epd/gdey037z03.dart b/lib/util/epd/gdey037z03.dart index 2fa7c2f1..50287ed9 100644 --- a/lib/util/epd/gdey037z03.dart +++ b/lib/util/epd/gdey037z03.dart @@ -10,10 +10,10 @@ class Gdey037z03 extends Epd { @override get width => 240; // pixels - + @override get height => 416; // pixels - + @override get colors => [Colors.black, Colors.white, Colors.red]; @@ -24,4 +24,4 @@ class Gdey037z03 extends Epd { processingMethods.add(ImageProcessing.rwbTriColorDither); processingMethods.add(ImageProcessing.colorHalftone); } -} \ No newline at end of file +} diff --git a/lib/util/epd/gdey037z03bw.dart b/lib/util/epd/gdey037z03bw.dart index 052cac56..f6547e04 100644 --- a/lib/util/epd/gdey037z03bw.dart +++ b/lib/util/epd/gdey037z03bw.dart @@ -10,10 +10,10 @@ class Gdey037z03BW extends Epd { @override get width => 240; // pixels - + @override get height => 416; // pixels - + @override get colors => [Colors.black, Colors.white]; @@ -24,4 +24,4 @@ class Gdey037z03BW extends Epd { processingMethods.add(ImageProcessing.binaryDither); processingMethods.add(ImageProcessing.halftone); } -} \ No newline at end of file +} diff --git a/lib/util/image_processing/extract_quantizer.dart b/lib/util/image_processing/extract_quantizer.dart index bd9266cf..b3ca3b9a 100644 --- a/lib/util/image_processing/extract_quantizer.dart +++ b/lib/util/image_processing/extract_quantizer.dart @@ -14,7 +14,8 @@ class ExtractQuantizer extends img.Quantizer { this.sThres = 0.5, this.vThres = 0.5, }) : _palette = img.PaletteUint8(2, 3) { - _palette.setRgb(0, toBeExtract.red, toBeExtract.green, toBeExtract.blue); + _palette.setRgb(0, (toBeExtract.r * 255).toInt(), + (toBeExtract.g * 255).toInt(), (toBeExtract.b * 255).toInt()); _palette.setRgb(1, 255, 255, 255); _toBeExtract = HSVColor.fromColor(toBeExtract); } @@ -25,9 +26,11 @@ class ExtractQuantizer extends img.Quantizer { @override img.Color getQuantizedColor(img.Color c) { return _isIt(c) - ? img.ColorRgb8(_palette.getRed(0) as int, _palette.getGreen(0) as int, _palette.getBlue(0) as int) - : img.ColorRgb8(_palette.getRed(1) as int, _palette.getGreen(1) as int, _palette.getBlue(1) as int); - } + ? img.ColorRgb8(_palette.getRed(0) as int, _palette.getGreen(0) as int, + _palette.getBlue(0) as int) + : img.ColorRgb8(_palette.getRed(1) as int, _palette.getGreen(1) as int, + _palette.getBlue(1) as int); + } @override int getColorIndex(img.Color c) => _isIt(c) ? 0 : 1; @@ -46,9 +49,9 @@ class ExtractQuantizer extends img.Quantizer { } bool _hsvInRange(HSVColor v, HSVColor a, HSVColor b) { - return _inAngularRange(v.hue, a.hue, b.hue) - && _inLinearRange(v.saturation, a.saturation, b.saturation) - && _inLinearRange(v.value, a.value, b.value); + return _inAngularRange(v.hue, a.hue, b.hue) && + _inLinearRange(v.saturation, a.saturation, b.saturation) && + _inLinearRange(v.value, a.value, b.value); } bool _hsvColorThreshold(HSVColor v, HSVColor p) { @@ -56,22 +59,26 @@ class ExtractQuantizer extends img.Quantizer { final sHalfThres = sThres / 2; final vHalfThres = vThres / 2; - final sLower = p.saturation - sHalfThres < 0.0 ? 0.0 : p.saturation - sHalfThres; + final sLower = + p.saturation - sHalfThres < 0.0 ? 0.0 : p.saturation - sHalfThres; final vLower = p.value - vHalfThres < 0.0 ? 0.0 : p.value - vHalfThres; - final sUpper = p.saturation + sHalfThres > 1.0 ? 1.0 : p.saturation + sHalfThres; + final sUpper = + p.saturation + sHalfThres > 1.0 ? 1.0 : p.saturation + sHalfThres; final vUpper = p.value + vHalfThres > 1.0 ? 1.0 : p.value + vHalfThres; - final rangeA = HSVColor.fromAHSV(1, (p.hue - hHalfThres) % 360, sLower, vLower); - final rangeB = HSVColor.fromAHSV(1, (p.hue + hHalfThres) % 360, sUpper, vUpper); + final rangeA = + HSVColor.fromAHSV(1, (p.hue - hHalfThres) % 360, sLower, vLower); + final rangeB = + HSVColor.fromAHSV(1, (p.hue + hHalfThres) % 360, sUpper, vUpper); return _hsvInRange(v, rangeA, rangeB); - } bool _isIt(img.Color c) { - final dartColor = Color.fromRGBO(c.r as int, c.g as int, c.b as int, c.aNormalized as double); + final dartColor = Color.fromRGBO( + c.r as int, c.g as int, c.b as int, c.aNormalized as double); final hsvColor = HSVColor.fromColor(dartColor); return _hsvColorThreshold(hsvColor, _toBeExtract); } -} \ No newline at end of file +} diff --git a/lib/util/image_processing/image_processing.dart b/lib/util/image_processing/image_processing.dart index a81706d1..2a16a31c 100644 --- a/lib/util/image_processing/image_processing.dart +++ b/lib/util/image_processing/image_processing.dart @@ -67,4 +67,4 @@ class ImageProcessing { quantizer: RemapQuantizer(palette: palette), kernel: img.DitherKernel.none); } -} \ No newline at end of file +} diff --git a/lib/util/image_processing/remap_quantizer.dart b/lib/util/image_processing/remap_quantizer.dart index 8dd23418..02700c5f 100644 --- a/lib/util/image_processing/remap_quantizer.dart +++ b/lib/util/image_processing/remap_quantizer.dart @@ -16,7 +16,7 @@ class RemapQuantizer extends img.Quantizer { @override img.Color getQuantizedColor(img.Color c) { return _map(c).$1; - } + } @override int getColorIndex(img.Color c) { @@ -42,4 +42,4 @@ class RemapQuantizer extends img.Quantizer { final nearestIndex = ds.indexOf(ds.reduce(min)); return (_colorLut[nearestIndex], nearestIndex); } -} \ No newline at end of file +} diff --git a/lib/util/magic_epaper_firmware.dart b/lib/util/magic_epaper_firmware.dart index 0eee45e3..d9338eb3 100644 --- a/lib/util/magic_epaper_firmware.dart +++ b/lib/util/magic_epaper_firmware.dart @@ -4,4 +4,4 @@ class MagicEpaperFirmware { int get epdCmd => 0x00; // command packet, pull the epd's C/D pin to Low (CMD) int get epdSend => 0x01; // data packet, pull the epd's C/D pin to High (DATA) final tagChip = St25dv(); -} \ No newline at end of file +} diff --git a/lib/util/protocol.dart b/lib/util/protocol.dart index cc0bfbbb..abc08308 100644 --- a/lib/util/protocol.dart +++ b/lib/util/protocol.dart @@ -1,7 +1,7 @@ - import 'dart:typed_data'; import 'package:convert/convert.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_nfc_kit/flutter_nfc_kit.dart'; import 'package:image/image.dart' as img; import 'package:magic_epaper_app/util/epd/edp.dart'; @@ -23,17 +23,13 @@ class Protocol { return await _transceive(fw.tagChip.writeMsgCmd, tagId, msg); } - Future _readMsg(Uint8List tagId) async { - // Send 0 will return all message present in the tag's mailbox - return await _transceive(fw.tagChip.readMsgDmd, tagId, Uint8List.fromList([0])); - } - Future _readDynCfg(Uint8List tagId, int address) async { final raw = fw.tagChip.buildReadDynCfgCmd(tagId, address); return await FlutterNfcKit.transceive(raw, timeout: timeout); } - Future _writeDynCfg(Uint8List tagId, int address, int value) async { + Future _writeDynCfg( + Uint8List tagId, int address, int value) async { final raw = fw.tagChip.buildWriteDynCfgCmd(tagId, address, value); return await FlutterNfcKit.transceive(raw, timeout: timeout); } @@ -70,23 +66,26 @@ class Protocol { Future writeFrame(Uint8List id, Uint8List frame, int cmd) async { final chunks = _split(data: frame); - await _writeMsg(id, Uint8List.fromList([fw.epdCmd, cmd])); // enter transmission 1 + await _writeMsg( + id, Uint8List.fromList([fw.epdCmd, cmd])); // enter transmission 1 await _sleep(); for (int i = 0; i < chunks.length; i++) { Uint8List chunk = chunks[i]; - print("Writing chunk ${i + 1}/${chunks.length} len ${chunk.lengthInBytes}: ${chunk.map((e) => e.toRadixString(16)).toList()}"); + debugPrint( + "Writing chunk ${i + 1}/${chunks.length} len ${chunk.lengthInBytes}: ${chunk.map((e) => e.toRadixString(16)).toList()}"); await _writeMsg(id, chunk); await wait4msgGathered(id); } - print("Transferred successfully."); + debugPrint("Transferred successfully."); } List _split({required Uint8List data, int chunkSize = 220}) { List chunks = []; for (int i = 0; i < data.length; i += chunkSize) { int end = (i + chunkSize > data.length) ? data.length : i + chunkSize; - Uint8List chunk = Uint8List.fromList([fw.epdSend, ...data.sublist(i, end)]); + Uint8List chunk = + Uint8List.fromList([fw.epdSend, ...data.sublist(i, end)]); chunks.add(chunk); } return chunks; @@ -98,9 +97,9 @@ class Protocol { throw "NFC is not available"; } - print("Bring your phone near to the Magic Epaper Hardware"); + debugPrint("Bring your phone near to the Magic Epaper Hardware"); final tag = await FlutterNfcKit.poll(timeout: timeout); - print("Got a tag!"); + debugPrint("Got a tag!"); var id = Uint8List.fromList(hex.decode(tag.id)); if (tag.type != NFCTagType.iso15693) { @@ -108,7 +107,8 @@ class Protocol { } await enableEnergyHarvesting(id); - await Future.delayed(const Duration(seconds: 2)); // waiting for the power supply stable + await Future.delayed( + const Duration(seconds: 2)); // waiting for the power supply stable final epdColors = epd.extractEpaperColorFrames(image); final transmissionLines = epd.controller.transmissionLines.iterator; @@ -117,7 +117,8 @@ class Protocol { await writeFrame(id, c, transmissionLines.current); } - await _writeMsg(id, Uint8List.fromList([fw.epdCmd, epd.controller.refresh])); + await _writeMsg( + id, Uint8List.fromList([fw.epdCmd, epd.controller.refresh])); await FlutterNfcKit.finish(); } -} \ No newline at end of file +} diff --git a/lib/util/st25dv.dart b/lib/util/st25dv.dart index bc6c3dfa..d3ea88ef 100644 --- a/lib/util/st25dv.dart +++ b/lib/util/st25dv.dart @@ -52,4 +52,4 @@ class St25dv { return b.toBytes(); } -} \ No newline at end of file +} diff --git a/lib/view/home_screen.dart b/lib/view/home_screen.dart index 61f2dd6f..ff6777fe 100644 --- a/lib/view/home_screen.dart +++ b/lib/view/home_screen.dart @@ -19,13 +19,19 @@ class SelectDisplay extends StatelessWidget { children: [ ElevatedButton( onPressed: () { - Navigator.push(context, MaterialPageRoute(builder: (context) => ImageEditor(epd: gdey037z03))); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ImageEditor(epd: gdey037z03))); }, child: Text(gdey037z03.description), ), ElevatedButton( onPressed: () { - Navigator.push(context, MaterialPageRoute(builder: (context) => ImageEditor(epd: gdey037z03bw))); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ImageEditor(epd: gdey037z03bw))); }, child: Text(gdey037z03bw.description), ), @@ -34,4 +40,4 @@ class SelectDisplay extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/view/image_editor.dart b/lib/view/image_editor.dart index f9bf6f9d..e3469a81 100644 --- a/lib/view/image_editor.dart +++ b/lib/view/image_editor.dart @@ -17,13 +17,17 @@ class ImageEditor extends StatelessWidget { final orgImg = imgLoader.image; if (orgImg != null) { - final image = img.copyResize(imgLoader.image!, width: epd.width, height: epd.height); + final image = img.copyResize(imgLoader.image!, + width: epd.width, height: epd.height); for (final method in epd.processingMethods) { processedImgs.add(method(image)); } } - final imgList = ImageList(imgList: processedImgs, epd: epd,); + final imgList = ImageList( + imgList: processedImgs, + epd: epd, + ); return Scaffold( appBar: AppBar( title: const Text('Edit Image'), @@ -36,11 +40,7 @@ class ImageEditor extends StatelessWidget { ), ], ), - - body: Center( - child: imgList - ), - + body: Center(child: imgList), ); } } diff --git a/lib/view/widget/image_list.dart b/lib/view/widget/image_list.dart index 746f7ce8..b8e75867 100644 --- a/lib/view/widget/image_list.dart +++ b/lib/view/widget/image_list.dart @@ -27,27 +27,27 @@ class _ImageList extends State { for (var i in widget.imgList) { var rotatedImg = img.copyRotate(i, angle: 90); - var uiImage = Image.memory(img.encodePng(rotatedImg), height: 100, isAntiAlias: false); + var uiImage = Image.memory(img.encodePng(rotatedImg), + height: 100, isAntiAlias: false); imgWidgets.add(uiImage); } - return Column(children: [ - for (int index = 0; index < imgWidgets.length; index++) - ListTile( - title: imgWidgets[index], - leading: Radio( - value: index, - groupValue: imgSelection, - onChanged: (int? value) { - setState(() { - imgSelection = value!; - }); - }, + return Column( + children: [ + for (int index = 0; index < imgWidgets.length; index++) + ListTile( + title: imgWidgets[index], + leading: Radio( + value: index, + groupValue: imgSelection, + onChanged: (int? value) { + setState(() { + imgSelection = value!; + }); + }, + ), ), - ), - - Expanded(child:Container()), - + Expanded(child: Container()), ElevatedButton( onPressed: () { Protocol(epd: widget.epd).writeImages(widget.imgList[imgSelection]); @@ -57,4 +57,4 @@ class _ImageList extends State { ], ); } -} \ No newline at end of file +} diff --git a/pubspec.lock b/pubspec.lock index 1cf49302..48db45a0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,42 +21,42 @@ packages: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.12.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.1" convert: dependency: "direct main" description: @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" file_selector_linux: dependency: transitive description: @@ -337,18 +337,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -377,10 +377,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -401,10 +401,10 @@ packages: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.16.0" mime: dependency: transitive description: @@ -433,10 +433,10 @@ packages: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_parsing: dependency: transitive description: @@ -473,15 +473,15 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" sprintf: dependency: transitive description: @@ -494,42 +494,42 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.4" typed_data: dependency: transitive description: @@ -582,10 +582,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "14.3.1" web: dependency: transitive description: @@ -603,5 +603,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.5.4 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.7.0-0 <4.0.0" + flutter: ">=3.29.2" diff --git a/pubspec.yaml b/pubspec.yaml index f13d77f5..bc2c05c1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,8 @@ publish_to: 'none' version: 1.0.0+1 environment: - sdk: ^3.5.4 + sdk: '>=3.3.4 <4.0.0' + flutter: '3.29.2' dependencies: flutter: