chore(macos): app store preparations, ui adjustments

This commit is contained in:
2026-05-16 01:05:47 +03:00
parent ec689d2940
commit db7cc6ffab
51 changed files with 408 additions and 26 deletions

View File

@@ -95,7 +95,9 @@ jobs:
release-type: dart
scopes: |
ios: fastlane/metadata/ios/en-US/changelogs
apple: fastlane/metadata/ios/en-US/changelogs
apple: |
fastlane/metadata/ios/en-US/changelogs
fastlane/metadata/macos/en-US/changelogs
android: fastlane/metadata/android/en-US/changelogs
build-android:
@@ -112,9 +114,9 @@ jobs:
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'gradle'
distribution: "temurin"
java-version: "17"
cache: "gradle"
- name: Setup Flutter
uses: subosito/flutter-action@v2

View File

@@ -40,12 +40,15 @@ help:
@echo " android-build-aab Build Android App Bundle"
@echo " android-push Build APK and push to device via adb"
@echo " ios-build Build iOS (no codesign)"
@echo " macos-build Build macOS app (.app bundle, no codesign)"
@echo " macos-build-pkg Build signed macOS .pkg for App Store"
@echo " build-all Build all platforms"
@echo ""
@echo " Release:"
@echo " android-release-apk Build APK and copy to build/release/"
@echo " android-release-aab Build AAB and copy to build/release/"
@echo " ios-release Build IPA and copy to build/release/"
@echo " macos-release Build PKG and copy to build/release/"
@echo " release-all Build and release all platforms"
@echo ""
@echo " Deploying:"
@@ -53,6 +56,8 @@ help:
@echo " android-promote Promote release between tracks (FROM=internal, TO=production, STATUS=draft|completed)"
@echo " ios-deploy Build IPA and upload (DEST=testflight|appstore, default: testflight)"
@echo " ios-submit Submit the existing App Store build for review (no upload)"
@echo " macos-deploy Build PKG and upload (DEST=testflight|appstore, default: testflight)"
@echo " macos-submit Submit the existing Mac App Store build for review (no upload)"
@echo " deploy-production Build and deploy to production (Google Play + App Store)"
@echo " deploy-beta Build and deploy to beta (Google Play beta + TestFlight)"
@@ -137,6 +142,26 @@ ios-build:
ios-build-ipa:
flutter build ipa --release --obfuscate --split-debug-info=build/debug-info-ios --dart-define-from-file=.env --export-options-plist=ios/ExportOptions.plist
.PHONY: macos-build
macos-build:
flutter build macos --release --obfuscate --split-debug-info=build/debug-info-macos
.PHONY: macos-build-pkg
macos-build-pkg:
flutter build macos --config-only --obfuscate --split-debug-info=build/debug-info-macos
rm -rf build/macos/Runner.xcarchive build/macos/pkg
xcodebuild -workspace macos/Runner.xcworkspace \
-scheme Runner \
-configuration Release \
-archivePath build/macos/Runner.xcarchive \
-allowProvisioningUpdates \
archive
xcodebuild -exportArchive \
-archivePath build/macos/Runner.xcarchive \
-exportPath build/macos/pkg \
-exportOptionsPlist macos/ExportOptions.plist \
-allowProvisioningUpdates
.PHONY: build-all
build-all: android-build-apk android-build-aab
@@ -159,6 +184,12 @@ ios-release: ios-build-ipa
cp build/ios/ipa/*.ipa build/release/pantry-$(VERSION).ipa
@echo "-> build/release/pantry-$(VERSION).ipa"
.PHONY: macos-release
macos-release: macos-build-pkg
mkdir -p build/release
cp build/macos/pkg/*.pkg build/release/pantry-$(VERSION).pkg
@echo "-> build/release/pantry-$(VERSION).pkg"
.PHONY: android-upload
android-upload:
@echo "$(or $(TRACK),beta)" | grep -qE '^(internal|alpha|beta|production)$$' || (echo "Error: Invalid TRACK '$(TRACK)'. Must be: internal, alpha, beta, production"; exit 1)
@@ -194,6 +225,23 @@ ios-deploy: ios-build-ipa ios-upload
ios-submit:
bundle exec fastlane ios submit
.PHONY: macos-upload
macos-upload:
@echo "$(or $(DEST),testflight)" | grep -qE '^(testflight|appstore)$$' || (echo "Error: Invalid DEST '$(DEST)'. Must be: testflight, appstore"; exit 1)
@echo "Destination: $(or $(DEST),testflight)"
@if [ "$(or $(DEST),testflight)" = "appstore" ]; then \
bundle exec fastlane mac release; \
else \
bundle exec fastlane mac beta; \
fi
.PHONY: macos-deploy
macos-deploy: macos-build-pkg macos-upload
.PHONY: macos-submit
macos-submit:
bundle exec fastlane mac submit
.PHONY: release-all
release-all: android-release-apk android-release-aab

View File

@@ -234,3 +234,90 @@ platform :ios do
)
end
end
# -- macOS --
platform :mac do
def api_key
key_id = ENV.fetch("APP_STORE_API_KEY")
app_store_connect_api_key(
key_id: key_id,
issuer_id: ENV.fetch("APP_STORE_ISSUER_ID"),
key_filepath: File.join(ENV.fetch("APP_STORE_KEY_PATH"), "AuthKey_#{key_id}.p8"),
)
end
def find_pkg
pkg_path = Dir[File.expand_path("../build/macos/pkg/*.pkg", __dir__)].first
UI.user_error!("No PKG found in build/macos/pkg/. Run 'make macos-build-pkg' first.") unless pkg_path
pkg_path
end
def sync_release_notes
version_code = version_info[:build]
changelog_file = File.expand_path("metadata/macos/en-US/changelogs/#{version_code}.txt", __dir__)
notes = File.exist?(changelog_file) ? File.read(changelog_file).strip : changelog_notes
release_notes_path = File.expand_path("metadata/macos/en-US/release_notes.txt", __dir__)
File.write(release_notes_path, notes)
UI.message("Synced release notes from build #{version_code} (#{notes.length} chars)")
notes
end
desc "Upload to TestFlight (macOS)"
lane :beta do
notes = sync_release_notes
upload_to_testflight(
api_key: api_key,
pkg: find_pkg,
app_platform: "osx",
changelog: notes,
skip_waiting_for_build_processing: true,
)
end
desc "Upload to Mac App Store"
lane :release do
sync_release_notes
deliver(
api_key: api_key,
pkg: find_pkg,
platform: "osx",
metadata_path: File.expand_path("metadata/macos", __dir__),
screenshots_path: File.expand_path("metadata/macos/en-US/screenshots", __dir__),
skip_screenshots: true,
submit_for_review: true,
precheck_include_in_app_purchases: false,
force: true,
)
end
desc "Sync macOS metadata only (no PKG upload)"
lane :metadata do
deliver(
api_key: api_key,
platform: "osx",
metadata_path: File.expand_path("metadata/macos", __dir__),
screenshots_path: File.expand_path("metadata/macos/en-US/screenshots", __dir__),
skip_binary_upload: true,
skip_screenshots: true,
submit_for_review: false,
precheck_include_in_app_purchases: false,
force: true,
)
end
desc "Submit existing Mac App Store build for review (no PKG upload)"
lane :submit do
deliver(
api_key: api_key,
platform: "osx",
metadata_path: File.expand_path("metadata/macos", __dir__),
screenshots_path: File.expand_path("metadata/macos/en-US/screenshots", __dir__),
skip_binary_upload: true,
skip_screenshots: true,
submit_for_review: true,
precheck_include_in_app_purchases: false,
force: true,
)
end
end

View File

@@ -78,6 +78,43 @@ Submit existing App Store build for review (no IPA upload)
----
## Mac
### mac beta
```sh
[bundle exec] fastlane mac beta
```
Upload to TestFlight (macOS)
### mac release
```sh
[bundle exec] fastlane mac release
```
Upload to Mac App Store
### mac metadata
```sh
[bundle exec] fastlane mac metadata
```
Sync macOS metadata only (no PKG upload)
### mac submit
```sh
[bundle exec] fastlane mac submit
```
Submit existing Mac App Store build for review (no PKG upload)
----
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).

View File

@@ -0,0 +1 @@
2026 Chen Asraf

View File

@@ -0,0 +1,5 @@
Features
- add setting to show spacing between categories in checklist items
- create new lists from the list selector
- share photos, links, and text to Pantry from other apps
- take photos directly from the photo board

View File

@@ -0,0 +1,25 @@
Pantry is a companion app for the Nextcloud Pantry server app. It lets you and your household members collaborate on shared checklists, a photo board, and a notes wall — all stored on your own Nextcloud server.
* Checklists
Create shopping lists and to-do lists with categories, quantities, recurring items, and images. Drag to reorder, sort by name or date, and check items off as you go.
* Photo Board
Upload and organize photos into folders. Add captions, drag to reorder, and browse everything in a clean grid view.
* Notes Wall
Keep shared notes with your household. Color-code them, write in markdown, and pin the important stuff where everyone can see it.
* Your data, your server
Pantry connects directly to your Nextcloud instance. No accounts to create, no cloud services in between. Your data never leaves your server.
* Features
- Shared checklists with categories, quantities, and recurrence
- Photo board with folders, captions, and multi-upload
- Color-coded notes wall
- Drag-and-drop reordering everywhere
- Multi-select for bulk actions
- Offline caching for fast loading
- Material Design 3 with dark mode support
- Secure login flow authentication
* Requires a Nextcloud server with the Pantry app installed. Visit the project page for setup instructions.

View File

@@ -0,0 +1 @@
nextcloud, checklist, todo, shopping list, notes, self-hosted, household

View File

@@ -0,0 +1 @@
https://github.com/chenasraf/pantry-flutter

View File

@@ -0,0 +1 @@
Pantry for Nextcloud

View File

@@ -0,0 +1 @@
https://casraf.dev/pantry-privacy-policy

View File

@@ -0,0 +1 @@
Manage your household on your Nextcloud — shared lists, photos & notes.

View File

@@ -0,0 +1,5 @@
Features
- add setting to show spacing between categories in checklist items
- create new lists from the list selector
- share photos, links, and text to Pantry from other apps
- take photos directly from the photo board

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1 @@
Home lists, photos & notes

View File

@@ -0,0 +1 @@
https://github.com/chenasraf/pantry-flutter

View File

@@ -0,0 +1 @@
PRODUCTIVITY

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@
EQq38!t9uA!@RdAkn6umJHo@nDh3ZZwM

View File

@@ -0,0 +1 @@
store-test

View File

@@ -0,0 +1 @@
casraf@pm.me

View File

@@ -0,0 +1 @@
Chen

View File

@@ -0,0 +1 @@
Asraf

View File

@@ -0,0 +1,3 @@
1. In the login screen, for the server, use: spider.casraf.dev and click "Connect"
2. Use the given username/password to sign in to the Nextcloud website loaded in the default browser
3. Click "Grant Access" to grant access to the app inside the in-app browser

View File

@@ -0,0 +1 @@
+972549107970

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -1,4 +1,40 @@
PODS:
- device_info_plus (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.9):
- DKImagePickerController/ImageDataManager
- DKImagePickerController/Resource
- DKImagePickerController/ImageDataManager (4.3.9)
- DKImagePickerController/PhotoGallery (4.3.9):
- DKImagePickerController/Core
- DKPhotoGallery
- DKImagePickerController/Resource (4.3.9)
- DKPhotoGallery (0.0.19):
- DKPhotoGallery/Core (= 0.0.19)
- DKPhotoGallery/Model (= 0.0.19)
- DKPhotoGallery/Preview (= 0.0.19)
- DKPhotoGallery/Resource (= 0.0.19)
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Core (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Preview
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Model (0.0.19):
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Preview (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Resource
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
- Flutter (1.0.0)
- flutter_local_notifications (0.0.1):
- Flutter
@@ -13,9 +49,13 @@ PODS:
- Flutter
- receive_sharing_intent (1.8.1):
- Flutter
- SDWebImage (5.21.7):
- SDWebImage/Core (= 5.21.7)
- SDWebImage/Core (5.21.7)
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- SwiftyGif (5.4.5)
- url_launcher_ios (0.0.1):
- Flutter
- wakelock_plus (0.0.1):
@@ -24,6 +64,8 @@ PODS:
- Flutter
DEPENDENCIES:
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
@@ -36,7 +78,18 @@ DEPENDENCIES:
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
- workmanager_apple (from `.symlinks/plugins/workmanager_apple/ios`)
SPEC REPOS:
trunk:
- DKImagePickerController
- DKPhotoGallery
- SDWebImage
- SwiftyGif
EXTERNAL SOURCES:
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
Flutter:
:path: Flutter
flutter_local_notifications:
@@ -61,6 +114,10 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/workmanager_apple/ios"
SPEC CHECKSUMS:
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_local_notifications: 395056b3175ba4f08480a7c5de30cd36d69827e4
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
@@ -68,7 +125,9 @@ SPEC CHECKSUMS:
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
workmanager_apple: 904529ae31e97fc5be632cf628507652294a0778

View File

@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@@ -116,13 +117,15 @@ class PantryAppState extends State<PantryApp> {
Widget build(BuildContext context) {
final color = ThemingService.instance.effectiveColor;
final locale = LocaleService.instance.effectiveLocale;
final isMacOS = !kIsWeb && Platform.isMacOS;
final appBarTheme = isMacOS ? const AppBarTheme(toolbarHeight: 66) : null;
return ChangeNotifierProvider<PrefsService>.value(
value: PrefsService.instance,
child: Directionality(
textDirection: LocaleService.instance.textDirection,
child: MaterialApp(
key: ValueKey(locale),
// debugShowCheckedModeBanner: false,
debugShowCheckedModeBanner: false,
navigatorKey: rootNavigatorKey,
locale: locale,
supportedLocales: supportedLocales,
@@ -137,6 +140,7 @@ class PantryAppState extends State<PantryApp> {
seedColor: color,
).copyWith(primary: color),
useMaterial3: true,
appBarTheme: appBarTheme,
popupMenuTheme: PopupMenuThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
@@ -151,6 +155,7 @@ class PantryAppState extends State<PantryApp> {
brightness: Brightness.dark,
).copyWith(primary: color),
useMaterial3: true,
appBarTheme: appBarTheme,
popupMenuTheme: PopupMenuThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),

View File

@@ -4,6 +4,7 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:pantry/i18n.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
class AboutView extends StatefulWidget {
const AboutView({super.key});
@@ -35,7 +36,7 @@ class _AboutViewState extends State<AboutView> {
final a = m.about;
return Scaffold(
appBar: AppBar(title: Text(a.title)),
appBar: AppBar(leading: appBarBackLeading(context), title: Text(a.title)),
body: ListView(
padding: const EdgeInsets.all(24),
children: [

View File

@@ -3,6 +3,7 @@ import 'package:pantry/i18n.dart';
import 'package:pantry/models/category.dart';
import 'package:pantry/services/category_service.dart';
import 'package:pantry/utils/category_icons.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
import 'package:pantry/widgets/create_category_dialog.dart';
class CategoriesView extends StatefulWidget {
@@ -125,7 +126,10 @@ class _CategoriesViewState extends State<CategoriesView> {
final theme = Theme.of(context);
return Scaffold(
appBar: AppBar(title: Text(m.categories.manageTitle)),
appBar: AppBar(
leading: appBarBackLeading(context),
title: Text(m.categories.manageTitle),
),
floatingActionButton: FloatingActionButton(
onPressed: _create,
child: const Icon(Icons.add),

View File

@@ -11,6 +11,7 @@ import 'package:pantry/utils/category_icons.dart';
import 'package:pantry/utils/date_format.dart';
import 'package:pantry/utils/rrule.dart';
import 'package:pantry/utils/text_direction.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
import 'checklists_controller.dart';
import 'item_form_view.dart';
@@ -53,6 +54,8 @@ class ItemDetailView extends StatelessWidget {
SliverAppBar(
expandedHeight: hasImage ? 280 : 0,
pinned: true,
toolbarHeight: theme.appBarTheme.toolbarHeight ?? kToolbarHeight,
leading: appBarBackLeading(context),
title: Directionality(
textDirection: nameDir,
child: Text(item.name),

View File

@@ -10,6 +10,7 @@ import 'package:pantry/models/checklist.dart';
import 'package:pantry/services/auth_service.dart';
import 'package:pantry/services/checklist_service.dart';
import 'package:pantry/utils/text_direction.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
import 'package:pantry/widgets/category_picker.dart';
import 'package:pantry/widgets/recurrence_dialog.dart';
import 'package:pantry/widgets/repeat_button.dart';
@@ -151,7 +152,10 @@ class _ItemFormViewState extends State<ItemFormView> {
final f = m.checklists.itemForm;
return Scaffold(
appBar: AppBar(title: Text(_isEditing ? f.editTitle : f.addTitle)),
appBar: AppBar(
leading: appBarBackLeading(context),
title: Text(_isEditing ? f.editTitle : f.addTitle),
),
floatingActionButton: FloatingActionButton(
onPressed: _saving ? null : _save,
child: _saving

View File

@@ -6,6 +6,7 @@ import 'package:pantry/models/note.dart';
import 'package:pantry/utils/text_direction.dart';
import 'package:pantry/views/notes/note_form_view.dart';
import 'package:pantry/views/notes/notes_controller.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
class NoteDetailView extends StatelessWidget {
final Note note;
@@ -32,15 +33,8 @@ class NoteDetailView extends StatelessWidget {
appBar: AppBar(
backgroundColor: bgColor,
foregroundColor: textColor,
title: Align(
alignment: titleDir == TextDirection.rtl
? Alignment.centerRight
: Alignment.centerLeft,
child: Directionality(
textDirection: titleDir,
child: Text(note.title),
),
),
leading: appBarBackLeading(context),
title: Directionality(textDirection: titleDir, child: Text(note.title)),
),
floatingActionButton: FloatingActionButton(
heroTag: null,

View File

@@ -4,6 +4,7 @@ import 'package:pantry/i18n.dart';
import 'package:pantry/models/note.dart';
import 'package:pantry/utils/text_direction.dart';
import 'package:pantry/views/notes/notes_controller.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
const _colorOptions = <String?>[
null, // default / no color
@@ -134,6 +135,7 @@ class _NoteFormViewState extends State<NoteFormView> {
appBar: AppBar(
backgroundColor: bgColor,
foregroundColor: textColor,
leading: appBarBackLeading(context),
title: Text(_isEditing ? m.notesWall.editNote : m.notesWall.newNote),
),
floatingActionButton: FloatingActionButton(

View File

@@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
import 'package:pantry/i18n.dart';
import 'package:pantry/models/notification.dart';
import 'package:pantry/services/deep_link_service.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
import 'notifications_controller.dart';
class NotificationsView extends StatefulWidget {
@@ -53,6 +54,7 @@ class _NotificationsBody extends StatelessWidget {
return Scaffold(
appBar: AppBar(
leading: appBarBackLeading(context),
title: Text(m.notifications.title),
actions: [
if (controller.notifications.isNotEmpty)

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:pantry/models/photo.dart';
import 'package:pantry/views/photos/photo_board_controller.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
class PhotoDetailView extends StatelessWidget {
final Photo photo;
@@ -21,7 +22,10 @@ class PhotoDetailView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(photo.caption ?? '')),
appBar: AppBar(
leading: appBarBackLeading(context),
title: Text(photo.caption ?? ''),
),
body: InteractiveViewer(
child: Center(
child: CachedNetworkImage(

View File

@@ -7,6 +7,7 @@ import 'package:pantry/services/local_notifications_service.dart';
import 'package:pantry/services/locale_service.dart';
import 'package:pantry/services/prefs_service.dart';
import 'package:pantry/services/theming_service.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
class SettingsView extends StatefulWidget {
const SettingsView({super.key});
@@ -132,7 +133,10 @@ class _SettingsViewState extends State<SettingsView> {
final categorySpacing = prefs.checklistCategorySpacing;
return Scaffold(
appBar: AppBar(title: Text(m.settings.title)),
appBar: AppBar(
leading: appBarBackLeading(context),
title: Text(m.settings.title),
),
body: ListView(
children: [
// -- General --

View File

@@ -10,6 +10,7 @@ import 'package:pantry/services/pending_note_share_service.dart';
import 'package:pantry/services/pending_photo_share_service.dart';
import 'package:pantry/services/photo_service.dart';
import 'package:pantry/services/prefs_service.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
/// Entry screen for an incoming OS share intent. Classifies the payload,
/// optionally asks the user to pick a house, and then routes:
@@ -174,7 +175,10 @@ class _ShareRouterViewState extends State<ShareRouterView> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(m.share.title)),
appBar: AppBar(
leading: appBarBackLeading(context),
title: Text(m.share.title),
),
body: Center(
child: _busy
? const CircularProgressIndicator()

View File

@@ -0,0 +1,14 @@
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
Widget? appBarBackLeading(BuildContext context) {
if (kIsWeb || !Platform.isMacOS) return null;
final route = ModalRoute.of(context);
if (route?.canPop != true) return null;
return const Align(
alignment: AlignmentDirectional.bottomCenter,
child: BackButton(),
);
}

View File

@@ -1,6 +1,8 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:pantry/widgets/app_bar_back_leading.dart';
class ImagePreview extends StatelessWidget {
final String imageUrl;
final Map<String, String> headers;
@@ -45,6 +47,7 @@ class ImagePreview extends StatelessWidget {
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
elevation: 0,
leading: appBarBackLeading(context),
),
body: InteractiveViewer(
minScale: 0.5,

View File

@@ -1,3 +1,4 @@
import 'dart:io' show Platform;
import 'dart:math' as math;
import 'package:file_picker/file_picker.dart';
@@ -21,6 +22,7 @@ class _PhotoAddButtonState extends State<PhotoAddButton>
with SingleTickerProviderStateMixin {
late final AnimationController _animController;
bool _open = false;
bool _cameraSupported = !Platform.isMacOS;
@override
void initState() {
@@ -29,6 +31,12 @@ class _PhotoAddButtonState extends State<PhotoAddButton>
vsync: this,
duration: const Duration(milliseconds: 380),
);
if (_cameraSupported) {
isiOSAppOnMac().then((onMac) {
if (!mounted || !onMac) return;
setState(() => _cameraSupported = false);
});
}
}
@override
@@ -54,7 +62,7 @@ class _PhotoAddButtonState extends State<PhotoAddButton>
Future<void> _pickPhotos() async {
_close();
final useFilePicker = await isiOSAppOnMac();
final useFilePicker = Platform.isMacOS || await isiOSAppOnMac();
if (useFilePicker) {
final result = await FilePicker.pickFiles(
allowMultiple: true,
@@ -135,6 +143,7 @@ class _PhotoAddButtonState extends State<PhotoAddButton>
label: m.photoBoard.addMenu.upload,
onTap: _pickPhotos,
),
if (_cameraSupported)
_FabAction(
icon: Icons.camera_alt,
label: m.photoBoard.addMenu.camera,

18
macos/ExportOptions.plist Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store-connect</string>
<key>destination</key>
<string>export</string>
<key>signingStyle</key>
<string>automatic</string>
<key>stripSwiftSymbols</key>
<true/>
<key>uploadSymbols</key>
<true/>
<key>teamID</key>
<string>Y893L6NQP2</string>
</dict>
</plist>

View File

@@ -1,4 +1,8 @@
PODS:
- device_info_plus (0.0.1):
- FlutterMacOS
- file_picker (0.0.1):
- FlutterMacOS
- file_selector_macos (0.0.1):
- FlutterMacOS
- flutter_local_notifications (0.0.1):
@@ -18,6 +22,8 @@ PODS:
- FlutterMacOS
DEPENDENCIES:
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
- flutter_secure_storage_darwin (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
@@ -28,6 +34,10 @@ DEPENDENCIES:
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
EXTERNAL SOURCES:
device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
file_picker:
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
file_selector_macos:
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
flutter_local_notifications:
@@ -46,6 +56,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
SPEC CHECKSUMS:
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7
flutter_local_notifications: 13862b132e32eb858dea558a86d45d08daeacfe7
flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23

View File

@@ -10,6 +10,8 @@
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)dev.casraf.pantry</string>

View File

@@ -18,6 +18,10 @@
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationCategoryType</key>
<string>public.app-category.productivity</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSMinimumSystemVersion</key>

View File

@@ -6,6 +6,8 @@
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)dev.casraf.pantry</string>