1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-24 10:37:28 +02:00

chore(mobile): Upgrade to Flutter 3.7 (#1416)

This commit is contained in:
Alex 2023-02-11 14:23:32 -06:00 committed by GitHub
parent ad9373312b
commit 09ab06ae6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1307 additions and 706 deletions

View File

@ -39,7 +39,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: "3.3.10"
flutter-version: "3.7.3"
cache: true
- name: Create the Keystore

View File

@ -19,7 +19,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.3.10'
flutter-version: '3.7.3'
- name: Install dependencies
run: dart pub get

View File

@ -49,7 +49,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.3.10'
flutter-version: '3.7.3'
- name: Run tests
working-directory: ./mobile
run: flutter test
@ -78,7 +78,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.3.10'
flutter-version: '3.7.3'
- name: Run integration tests
uses: reactivecircus/android-emulator-runner@v2.27.0
with:

View File

@ -2,6 +2,11 @@
xmlns:tools="http://schemas.android.com/tools">
<application android:label="Immich" android:name=".ImmichApp" android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher" android:requestLegacyExternalStorage="true">
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" />
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"

View File

@ -7,7 +7,8 @@ void main() async {
await ImmichTestHelper.initialize();
group("Login input validation test", () {
immichWidgetTest("Test leading/trailing whitespace", (tester, helper) async {
immichWidgetTest("Test leading/trailing whitespace",
(tester, helper) async {
await helper.loginHelper.waitForLoginScreen();
await helper.loginHelper.acknowledgeNewServerVersion();
@ -17,15 +18,21 @@ void main() async {
await tester.pump(const Duration(milliseconds: 300));
expect(find.text("login_form_err_leading_whitespace".tr()), findsOneWidget);
expect(
find.text("login_form_err_leading_whitespace".tr()),
findsOneWidget,
);
await helper.loginHelper.enterCredentials(
email: "demo@immich.app ",
email: "demo@immich.app ",
);
await tester.pump(const Duration(milliseconds: 300));
expect(find.text("login_form_err_trailing_whitespace".tr()), findsOneWidget);
expect(
find.text("login_form_err_trailing_whitespace".tr()),
findsOneWidget,
);
});
immichWidgetTest("Test invalid email", (tester, helper) async {
@ -33,13 +40,12 @@ void main() async {
await helper.loginHelper.acknowledgeNewServerVersion();
await helper.loginHelper.enterCredentials(
email: "demo.immich.app",
email: "demo.immich.app",
);
await tester.pump(const Duration(milliseconds: 300));
expect(find.text("login_form_err_invalid_email".tr()), findsOneWidget);
});
});
}

View File

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
platform :ios, '11.0'
# platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@ -34,19 +34,8 @@ target 'Runner' do
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
# post_install do |installer|
# installer.pods_project.targets.each do |target|
# flutter_additional_ios_build_settings(target)
# end
# end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
config.build_settings['ENABLE_BITCODE'] = 'YES'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
end
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

View File

@ -21,16 +21,18 @@ PODS:
- Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider_ios (0.0.1):
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- photo_manager (2.0.0):
- Flutter
- FlutterMacOS
- SAMKeychain (1.5.3)
- share_plus (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
@ -52,10 +54,10 @@ DEPENDENCIES:
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
@ -86,14 +88,14 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/isar_flutter_libs/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
photo_manager:
:path: ".symlinks/plugins/photo_manager/ios"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_ios:
:path: ".symlinks/plugins/shared_preferences_ios/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
@ -108,23 +110,23 @@ SPEC CHECKSUMS:
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
flutter_udid: 0848809dbed4c055175747ae6a45a8b4f6771e1c
flutter_web_auth: c25208760459cec375a3c39f6a8759165ca0fa4d
fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
PODFILE CHECKSUM: 05c3056158482c567a3e0cdab1351ceeee238a07
PODFILE CHECKSUM: c798208781ca5116c4a3d5927d689946791f0189
COCOAPODS: 1.11.3

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@ -201,6 +201,7 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -237,6 +238,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -341,7 +343,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
NEW_SETTING = "";
SDKROOT = iphoneos;
@ -425,7 +427,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
NEW_SETTING = "";
ONLY_ACTIVE_ARCH = YES;
@ -475,7 +477,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
NEW_SETTING = "";
SDKROOT = iphoneos;

File diff suppressed because one or more lines are too long

View File

@ -1,97 +1,101 @@
<?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>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Immich</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>immich_mobile</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.46.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>85</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MGLMapboxMetricsEnabledSettingShownInApp</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSLocationAlwaysUsageDescription</key>
<string>Enable location setting to show position of assets on map</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Enable location setting to show position of assets on map</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need to manage backup your photos album</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>We need to manage backup your photos album</string>
<key>NSCameraUsageDescription</key>
<string>We need to access the camera to let you take beautiful video using this app</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need to access the microphone to let you take beautiful video using this app</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
</array>
<key>CFBundleLocalizations</key>
<array>
<string>cs</string>
<string>da</string>
<string>de</string>
<string>en</string>
<string>es</string>
<string>fi</string>
<string>fr</string>
<string>it</string>
<string>ja</string>
<string>ko</string>
<string>nl</string>
<string>pl</string>
<string>pt</string>
<string>ru</string>
<string>sk</string>
<string>zh</string>
</array>
<key>UIStatusBarHidden</key>
<false/>
</dict>
</plist>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Immich</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>immich_mobile</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.46.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>85</string>
<key>LSRequiresIPhoneOS</key>
<true />
<key>MGLMapboxMetricsEnabledSettingShownInApp</key>
<true />
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true />
</dict>
<key>NSLocationAlwaysUsageDescription</key>
<string>Enable location setting to show position of assets on map</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Enable location setting to show position of assets on map</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need to manage backup your photos album</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>We need to manage backup your photos album</string>
<key>NSCameraUsageDescription</key>
<string>We need to access the camera to let you take beautiful video using this app</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need to access the microphone to let you take beautiful video using this app</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true />
<key>io.flutter.embedded_views_preview</key>
<true />
<key>ITSAppUsesNonExemptEncryption</key>
<false />
<key>CADisableMinimumFrameDurationOnPhone</key>
<true />
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
</array>
<key>CFBundleLocalizations</key>
<array>
<string>cs</string>
<string>da</string>
<string>de</string>
<string>en</string>
<string>es</string>
<string>fi</string>
<string>fr</string>
<string>it</string>
<string>ja</string>
<string>ko</string>
<string>nl</string>
<string>pl</string>
<string>pt</string>
<string>ru</string>
<string>sk</string>
<string>zh</string>
</array>
<key>UIStatusBarHidden</key>
<false />
<key>UIApplicationSupportsIndirectInputEvents</key>
<true />
<key>FLTEnableImpeller</key>
<true />
</dict>
</plist>

View File

@ -91,7 +91,7 @@ class AddToAlbumBottomSheet extends HookConsumerWidget {
children: [
Text(
'Add to album',
style: Theme.of(context).textTheme.headline2,
style: Theme.of(context).textTheme.displayMedium,
),
TextButton.icon(
icon: const Icon(Icons.add),

View File

@ -24,90 +24,97 @@ class AlbumThumbnailCard extends StatelessWidget {
var isDarkMode = Theme.of(context).brightness == Brightness.dark;
return LayoutBuilder(
builder: (context, constraints) {
var cardSize = constraints.maxWidth;
var cardSize = constraints.maxWidth;
buildEmptyThumbnail() {
return Container(
height: cardSize,
width: cardSize,
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[200],
),
child: Center(
child: Icon(
Icons.no_photography,
size: cardSize * .15,
buildEmptyThumbnail() {
return Container(
height: cardSize,
width: cardSize,
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[200],
),
),
);
}
child: Center(
child: Icon(
Icons.no_photography,
size: cardSize * .15,
),
),
);
}
buildAlbumThumbnail() {
return CachedNetworkImage(
width: cardSize,
height: cardSize,
fit: BoxFit.cover,
fadeInDuration: const Duration(milliseconds: 200),
imageUrl: getAlbumThumbnailUrl(
album,
type: ThumbnailFormat.JPEG,
),
httpHeaders: {"Authorization": "Bearer ${box.get(accessTokenKey)}"},
cacheKey: getAlbumThumbNailCacheKey(album, type: ThumbnailFormat.JPEG),
);
}
buildAlbumThumbnail() {
return CachedNetworkImage(
width: cardSize,
height: cardSize,
fit: BoxFit.cover,
fadeInDuration: const Duration(milliseconds: 200),
imageUrl: getAlbumThumbnailUrl(
album,
type: ThumbnailFormat.JPEG,
),
httpHeaders: {"Authorization": "Bearer ${box.get(accessTokenKey)}"},
cacheKey:
getAlbumThumbNailCacheKey(album, type: ThumbnailFormat.JPEG),
);
}
return GestureDetector(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.only(bottom: 32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
return GestureDetector(
onTap: onTap,
child: Flex(
direction: Axis.vertical,
children: [
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: album.albumThumbnailAssetId == null
? buildEmptyThumbnail()
: buildAlbumThumbnail(),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: SizedBox(
width: cardSize,
child: Text(
album.name,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
album.assetCount == 1
? 'album_thumbnail_card_item'
: 'album_thumbnail_card_items',
style: const TextStyle(
fontSize: 12,
),
).tr(args: ['${album.assetCount}']),
if (album.shared)
const Text(
'album_thumbnail_card_shared',
style: TextStyle(
fontSize: 12,
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: cardSize,
height: cardSize,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: album.albumThumbnailAssetId == null
? buildEmptyThumbnail()
: buildAlbumThumbnail(),
),
).tr()
],
)
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: SizedBox(
width: cardSize,
child: Text(
album.name,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
album.assetCount == 1
? 'album_thumbnail_card_item'
: 'album_thumbnail_card_items',
style: const TextStyle(
fontSize: 12,
),
).tr(args: ['${album.assetCount}']),
if (album.shared)
const Text(
'album_thumbnail_card_shared',
style: TextStyle(
fontSize: 12,
),
).tr()
],
)
],
),
),
],
),
),
);
);
},
);
}

View File

@ -34,7 +34,7 @@ class AlbumTitleTextField extends ConsumerWidget {
focusNode: albumTitleTextFieldFocusNode,
style: TextStyle(
fontSize: 28,
color: Colors.grey[700],
color: isDarkTheme ? Colors.grey[300] : Colors.grey[700],
fontWeight: FontWeight.bold,
),
controller: albumTitleController,

View File

@ -19,7 +19,7 @@ class CreateAlbumPage extends HookConsumerWidget {
final List<Asset>? initialAssets;
const CreateAlbumPage({
Key? key,
Key? key,
required this.isSharedAlbum,
this.initialAssets,
}) : super(key: key);
@ -84,7 +84,7 @@ class CreateAlbumPage extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 200, left: 18),
child: Text(
'create_shared_album_page_share_add_assets',
style: Theme.of(context).textTheme.headline2?.copyWith(
style: Theme.of(context).textTheme.displayMedium?.copyWith(
fontSize: 12,
fontWeight: FontWeight.normal,
),
@ -214,7 +214,7 @@ class CreateAlbumPage extends HookConsumerWidget {
),
title: Text(
'share_create_album',
style: Theme.of(context).textTheme.headline2?.copyWith(
style: Theme.of(context).textTheme.displayMedium?.copyWith(
color: Theme.of(context).primaryColor,
),
).tr(),
@ -228,7 +228,9 @@ class CreateAlbumPage extends HookConsumerWidget {
'create_shared_album_page_share'.tr(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).primaryColor,
color: albumTitleController.text.isEmpty
? Theme.of(context).disabledColor
: Theme.of(context).primaryColor,
),
),
),

View File

@ -15,6 +15,7 @@ class LibraryPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final albums = ref.watch(albumProvider);
var isDarkMode = Theme.of(context).brightness == Brightness.dark;
useEffect(
() {
@ -122,9 +123,12 @@ class LibraryPage extends HookConsumerWidget {
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
color: isDarkMode
? const Color.fromARGB(255, 53, 53, 53)
: const Color.fromARGB(255, 203, 203, 203),
),
borderRadius: BorderRadius.circular(8),
color: isDarkMode ? Colors.grey[900] : Colors.grey[50],
borderRadius: BorderRadius.circular(20),
),
child: Center(
child: Icon(
@ -168,25 +172,22 @@ class LibraryPage extends HookConsumerWidget {
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.0,
color: Theme.of(context).brightness == Brightness.dark
? Colors.white
: Colors.black,
color: isDarkMode ? Colors.white : Colors.black,
),
),
),
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.all(12),
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.grey[50],
side: BorderSide(
color: Theme.of(context).brightness == Brightness.dark
? Colors.grey[600]!
: Colors.grey[300]!,
color: isDarkMode ? Colors.grey[800]! : Colors.grey[300]!,
),
alignment: Alignment.centerLeft,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6.0),
),
),
icon: Icon(icon, color: Theme.of(context).primaryColor),
icon: Icon(
icon,
color: Theme.of(context).primaryColor,
),
),
);
}
@ -253,7 +254,7 @@ class LibraryPage extends HookConsumerWidget {
delegate: SliverChildBuilderDelegate(
childCount: sorted.length + 1,
(context, index) {
if (index == 0) {
if (index == 0) {
return buildCreateAlbumButton();
}

View File

@ -77,13 +77,13 @@ class SharingPage extends HookConsumerWidget {
child: Card(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), // if you need this
borderRadius: BorderRadius.circular(20),
side: const BorderSide(
color: Colors.grey,
width: 1,
width: 0.5,
),
),
color: Colors.transparent,
// color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
@ -92,7 +92,7 @@ class SharingPage extends HookConsumerWidget {
Padding(
padding: const EdgeInsets.only(left: 5.0, bottom: 5),
child: Icon(
Icons.offline_share_outlined,
Icons.insert_photo_rounded,
size: 50,
color: Theme.of(context).primaryColor,
),
@ -101,7 +101,7 @@ class SharingPage extends HookConsumerWidget {
padding: const EdgeInsets.all(8.0),
child: Text(
'sharing_page_empty_list',
style: Theme.of(context).textTheme.headline3,
style: Theme.of(context).textTheme.displaySmall,
).tr(),
),
Padding(

View File

@ -15,7 +15,7 @@ import 'package:immich_mobile/modules/asset_viewer/ui/top_control_app_bar.dart';
import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart';
import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart';
import 'package:immich_mobile/shared/services/asset.service.dart';
import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart';
import 'package:immich_mobile/modules/home/ui/delete_dialog.dart';
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
import 'package:immich_mobile/shared/ui/photo_view/photo_view_gallery.dart';
@ -213,7 +213,7 @@ class GalleryViewerPage extends HookConsumerWidget {
void handleSwipeUpDown(DragUpdateDetails details) {
int sensitivity = 15;
int dxThreshhold = 50;
int dxThreshold = 50;
if (isZoomed.value) {
return;
@ -222,7 +222,7 @@ class GalleryViewerPage extends HookConsumerWidget {
// Check for delta from initial down point
final d = details.localPosition - localPosition;
// If the magnitude of the dx swipe is large, we probably didn't mean to go down
if (d.dx.abs() > dxThreshhold) {
if (d.dx.abs() > dxThreshold) {
return;
}
@ -247,8 +247,8 @@ class GalleryViewerPage extends HookConsumerWidget {
isPlayingMotionVideo: isPlayingMotionVideo.value,
asset: assetList[indexOfAsset.value],
isFavorite: ref.watch(favoriteProvider).contains(
assetList[indexOfAsset.value].id,
),
assetList[indexOfAsset.value].id,
),
onMoreInfoPressed: () {
showInfo();
},
@ -314,7 +314,7 @@ class GalleryViewerPage extends HookConsumerWidget {
? (context, event) {
final asset = assetList[indexOfAsset.value];
if (!asset.isLocal) {
// Use the WEBP Thumbnail as a placeholder for the JPEG thumbnail to acheive
// Use the WEBP Thumbnail as a placeholder for the JPEG thumbnail to achieve
// Three-Stage Loading (WEBP -> JPEG -> Original)
final webPThumbnail = CachedNetworkImage(
imageUrl: getThumbnailUrl(

View File

@ -81,10 +81,6 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
child: GestureDetector(
onTap: removeSelection,
child: Chip(
visualDensity: VisualDensity.compact,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
label: Text(
album.name,
style: TextStyle(
@ -119,10 +115,6 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Chip(
visualDensity: VisualDensity.compact,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
label: Text(
album.name,
style: TextStyle(

View File

@ -92,11 +92,10 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
RenderAssetGridRow row,
bool scrolling,
) {
return LayoutBuilder(
builder: (context, constraints) {
final size = constraints.maxWidth / widget.assetsPerRow -
widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow;
widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow;
return Row(
key: Key("asset-row-${row.assets.first.id}"),
children: row.assets.mapIndexed((int index, Asset asset) {
@ -141,7 +140,7 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Theme.of(context).textTheme.headline1?.color,
color: Theme.of(context).textTheme.displayLarge?.color,
),
),
);

View File

@ -22,7 +22,7 @@ class MonthlyTitleText extends StatelessWidget {
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Theme.of(context).textTheme.headline1?.color,
color: Theme.of(context).textTheme.displayLarge?.color,
),
),
),

View File

@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/ui/add_to_album_sliverlist.dart';
import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart';
import 'package:immich_mobile/modules/home/ui/delete_dialog.dart';
import 'package:immich_mobile/shared/ui/drag_sheet.dart';
import 'package:immich_mobile/shared/models/album.dart';
@ -29,6 +29,8 @@ class ControlBottomAppBar extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
var isDarkMode = Theme.of(context).brightness == Brightness.dark;
Widget renderActionButtons() {
return Row(
children: [
@ -60,7 +62,6 @@ class ControlBottomAppBar extends ConsumerWidget {
);
},
),
],
);
}
@ -75,7 +76,9 @@ class ControlBottomAppBar extends ConsumerWidget {
ScrollController scrollController,
) {
return Card(
elevation: 12.0,
color: isDarkMode ? Colors.grey[900] : Colors.grey[100],
surfaceTintColor: Colors.transparent,
elevation: 18.0,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
@ -83,45 +86,37 @@ class ControlBottomAppBar extends ConsumerWidget {
),
),
margin: const EdgeInsets.all(0),
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
child: CustomScrollView(
controller: scrollController,
slivers: [
SliverToBoxAdapter(
child: Column(
children: <Widget>[
const SizedBox(height: 12),
const CustomDraggingHandle(),
const SizedBox(height: 12),
renderActionButtons(),
const Divider(
indent: 16,
endIndent: 16,
thickness: 1,
),
AddToAlbumTitleRow(onCreateNewAlbum: onCreateNewAlbum),
],
),
),
),
child: CustomScrollView(
controller: scrollController,
slivers: [
SliverToBoxAdapter(
child: Column(
children: <Widget>[
const SizedBox(height: 12),
const CustomDraggingHandle(),
const SizedBox(height: 12),
renderActionButtons(),
const Divider(
indent: 16,
endIndent: 16,
thickness: 1,
),
AddToAlbumTitleRow(onCreateNewAlbum: onCreateNewAlbum),
],
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: AddToAlbumSliverList(
albums: albums,
sharedAlbums: sharedAlbums,
onAddToAlbum: onAddToAlbum,
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: AddToAlbumSliverList(
albums: albums,
sharedAlbums: sharedAlbums,
onAddToAlbum: onAddToAlbum,
),
),
const SliverToBoxAdapter(
child: SizedBox(height: 200),
)
],
),
),
const SliverToBoxAdapter(
child: SizedBox(height: 200),
)
],
),
);
},

View File

@ -1,5 +1,4 @@
import 'package:auto_route/auto_route.dart';
import 'package:badges/badges.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
@ -29,7 +28,6 @@ class HomePageAppBar extends ConsumerWidget with PreferredSizeWidget {
final ServerInfoState serverInfoState = ref.watch(serverInfoProvider);
return AppBar(
centerTitle: true,
backgroundColor: Theme.of(context).appBarTheme.backgroundColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
@ -44,10 +42,9 @@ class HomePageAppBar extends ConsumerWidget with PreferredSizeWidget {
top: 5,
child: IconButton(
splashRadius: 25,
icon: Icon(
icon: const Icon(
Icons.face_outlined,
size: 30,
color: Theme.of(context).primaryColor,
),
onPressed: () {
Scaffold.of(context).openDrawer();
@ -112,16 +109,13 @@ class HomePageAppBar extends ConsumerWidget with PreferredSizeWidget {
splashRadius: 25,
iconSize: 30,
icon: isEnableAutoBackup
? Icon(
? const Icon(
Icons.backup_rounded,
color: Theme.of(context).primaryColor,
)
: Badge(
padding: const EdgeInsets.all(4),
elevation: 3,
position: BadgePosition.bottomEnd(bottom: -4, end: -4),
badgeColor: Colors.white,
badgeContent: const Icon(
backgroundColor: Colors.white,
label: const Icon(
Icons.cloud_off_rounded,
size: 8,
color: Colors.indigo,

View File

@ -15,7 +15,7 @@ class ProfileDrawer extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
buildSignoutButton() {
buildSignOutButton() {
return ListTile(
horizontalTitleGap: 0,
leading: SizedBox(
@ -95,6 +95,9 @@ class ProfileDrawer extends HookConsumerWidget {
}
return Drawer(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@ -105,7 +108,7 @@ class ProfileDrawer extends HookConsumerWidget {
const ProfileDrawerHeader(),
buildSettingButton(),
buildAppLogButton(),
buildSignoutButton(),
buildSignOutButton(),
],
),
const ServerInfoBox()

View File

@ -22,7 +22,7 @@ class ProfileDrawerHeader extends HookConsumerWidget {
AuthenticationState authState = ref.watch(authenticationProvider);
final uploadProfileImageStatus =
ref.watch(uploadProfileImageProvider).status;
var dummmy = Random().nextInt(1024);
var dummy = Random().nextInt(1024);
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
buildUserProfileImage() {
@ -39,7 +39,7 @@ class ProfileDrawerHeader extends HookConsumerWidget {
return CircleAvatar(
radius: 35,
backgroundImage: NetworkImage(
'$endpoint/user/profile-image/${authState.userId}?d=${dummmy++}',
'$endpoint/user/profile-image/${authState.userId}?d=${dummy++}',
),
backgroundColor: Colors.transparent,
);
@ -56,7 +56,7 @@ class ProfileDrawerHeader extends HookConsumerWidget {
return CircleAvatar(
radius: 35,
backgroundImage: NetworkImage(
'$endpoint/user/profile-image/${authState.userId}?d=${dummmy++}',
'$endpoint/user/profile-image/${authState.userId}?d=${dummy++}',
),
backgroundColor: Colors.transparent,
);

View File

@ -53,6 +53,9 @@ class SearchBar extends HookConsumerWidget with PreferredSizeWidget {
},
decoration: InputDecoration(
hintText: 'search_bar_hint'.tr(),
hintStyle: Theme.of(context).textTheme.titleSmall?.copyWith(
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
),

View File

@ -11,7 +11,6 @@ class TabControllerPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
navigationRail(TabsRouter tabsRouter) {
return NavigationRail(
labelType: NavigationRailLabelType.all,
@ -35,32 +34,33 @@ class TabControllerPage extends ConsumerWidget {
right: 4,
bottom: 4,
),
icon: const Icon(Icons.photo_outlined),
icon: const Icon(Icons.photo_outlined),
selectedIcon: const Icon(Icons.photo),
label: const Text('tab_controller_nav_photos').tr(),
),
NavigationRailDestination(
padding: const EdgeInsets.all(4),
icon: const Icon(Icons.search_rounded),
selectedIcon: const Icon(Icons.search),
icon: const Icon(Icons.search_rounded),
selectedIcon: const Icon(Icons.search),
label: const Text('tab_controller_nav_search').tr(),
),
NavigationRailDestination(
padding: const EdgeInsets.all(4),
icon: const Icon(Icons.share_rounded),
selectedIcon: const Icon(Icons.share),
icon: const Icon(Icons.share_rounded),
selectedIcon: const Icon(Icons.share),
label: const Text('tab_controller_nav_sharing').tr(),
),
NavigationRailDestination(
padding: const EdgeInsets.all(4),
icon: const Icon(Icons.photo_album_outlined),
selectedIcon: const Icon(Icons.photo_album),
icon: const Icon(Icons.photo_album_outlined),
selectedIcon: const Icon(Icons.photo_album),
label: const Text('tab_controller_nav_library').tr(),
),
],
);
}
// ignore: unused_element
bottomNavigationBar(TabsRouter tabsRouter) {
return BottomNavigationBar(
selectedLabelStyle: const TextStyle(
@ -101,6 +101,58 @@ class TabControllerPage extends ConsumerWidget {
);
}
experimentalNavigationBar(TabsRouter tabsRouter) {
return NavigationBar(
selectedIndex: tabsRouter.activeIndex,
onDestinationSelected: (index) {
HapticFeedback.selectionClick();
tabsRouter.setActiveIndex(index);
},
destinations: [
NavigationDestination(
label: 'tab_controller_nav_photos'.tr(),
icon: const Icon(
Icons.photo_outlined,
),
selectedIcon: Icon(
Icons.photo,
color: Theme.of(context).primaryColor,
),
),
NavigationDestination(
label: 'tab_controller_nav_search'.tr(),
icon: const Icon(
Icons.search_rounded,
),
selectedIcon: Icon(
Icons.search,
color: Theme.of(context).primaryColor,
),
),
NavigationDestination(
label: 'tab_controller_nav_sharing'.tr(),
icon: const Icon(
Icons.group_outlined,
),
selectedIcon: Icon(
Icons.group,
color: Theme.of(context).primaryColor,
),
),
NavigationDestination(
label: 'tab_controller_nav_library'.tr(),
icon: const Icon(
Icons.photo_album_outlined,
),
selectedIcon: Icon(
Icons.photo_album_rounded,
color: Theme.of(context).primaryColor,
),
)
],
);
}
final multiselectEnabled = ref.watch(multiselectProvider);
return AutoTabsRouter(
routes: [
@ -116,7 +168,7 @@ class TabControllerPage extends ConsumerWidget {
bool atHomeTab = tabsRouter.activeIndex == 0;
if (!atHomeTab) {
tabsRouter.setActiveIndex(0);
}
}
return atHomeTab;
},
@ -127,7 +179,7 @@ class TabControllerPage extends ConsumerWidget {
final Widget body;
if (constraints.maxWidth < medium) {
// Normal phone width
bottom = bottomNavigationBar(tabsRouter);
bottom = experimentalNavigationBar(tabsRouter);
body = FadeTransition(
opacity: animation,
child: child,
@ -146,13 +198,13 @@ class TabControllerPage extends ConsumerWidget {
),
],
);
} return Scaffold(
body: body,
bottomNavigationBar: multiselectEnabled
? null
: bottom,
);
},),
}
return Scaffold(
body: body,
bottomNavigationBar: multiselectEnabled ? null : bottom,
);
},
),
);
},
);

View File

@ -20,6 +20,83 @@ final immichThemeProvider = StateProvider<ThemeMode>((ref) {
}
});
ThemeData base = ThemeData(
chipTheme: const ChipThemeData(
side: BorderSide.none,
),
);
ThemeData immichLightTheme = ThemeData(
useMaterial3: true,
brightness: Brightness.light,
primarySwatch: Colors.indigo,
primaryColor: Colors.indigo,
hintColor: Colors.indigo,
fontFamily: 'WorkSans',
scaffoldBackgroundColor: immichBackgroundColor,
snackBarTheme: const SnackBarThemeData(
contentTextStyle: TextStyle(fontFamily: 'WorkSans'),
),
appBarTheme: AppBarTheme(
titleTextStyle: const TextStyle(
fontFamily: 'WorkSans',
color: Colors.indigo,
),
backgroundColor: immichBackgroundColor,
foregroundColor: Colors.indigo,
elevation: 0,
scrolledUnderElevation: 0,
centerTitle: true,
),
bottomNavigationBarTheme: BottomNavigationBarThemeData(
type: BottomNavigationBarType.fixed,
backgroundColor: immichBackgroundColor,
selectedItemColor: Colors.indigo,
),
cardTheme: const CardTheme(
surfaceTintColor: Colors.transparent,
),
drawerTheme: DrawerThemeData(
backgroundColor: immichBackgroundColor,
),
textTheme: const TextTheme(
displayLarge: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Colors.indigo,
),
displayMedium: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
displaySmall: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Colors.indigo,
),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.indigo,
foregroundColor: Colors.white,
),
),
chipTheme: base.chipTheme,
popupMenuTheme: const PopupMenuThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
surfaceTintColor: Colors.transparent,
color: Colors.white,
),
navigationBarTheme: NavigationBarThemeData(
indicatorColor: Colors.indigo.withOpacity(0.15),
backgroundColor: immichBackgroundColor,
surfaceTintColor: Colors.transparent,
),
);
ThemeData immichDarkTheme = ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
@ -43,7 +120,8 @@ ThemeData immichDarkTheme = ThemeData(
),
backgroundColor: const Color.fromARGB(255, 32, 33, 35),
foregroundColor: immichDarkThemePrimaryColor,
elevation: 1,
elevation: 0,
scrolledUnderElevation: 0,
centerTitle: true,
),
bottomNavigationBarTheme: BottomNavigationBarThemeData(
@ -56,17 +134,17 @@ ThemeData immichDarkTheme = ThemeData(
scrimColor: Colors.white.withOpacity(0.1),
),
textTheme: TextTheme(
headline1: const TextStyle(
displayLarge: const TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 255, 255, 255),
),
headline2: const TextStyle(
displayMedium: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 255, 255, 255),
),
headline3: TextStyle(
displaySmall: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: immichDarkThemePrimaryColor,
@ -79,57 +157,19 @@ ThemeData immichDarkTheme = ThemeData(
backgroundColor: immichDarkThemePrimaryColor,
),
),
);
ThemeData immichLightTheme = ThemeData(
useMaterial3: true,
brightness: Brightness.light,
primarySwatch: Colors.indigo,
hintColor: Colors.indigo,
fontFamily: 'WorkSans',
scaffoldBackgroundColor: immichBackgroundColor,
snackBarTheme: const SnackBarThemeData(
contentTextStyle: TextStyle(fontFamily: 'WorkSans'),
),
appBarTheme: AppBarTheme(
titleTextStyle: const TextStyle(
fontFamily: 'WorkSans',
color: Colors.indigo,
chipTheme: base.chipTheme,
popupMenuTheme: const PopupMenuThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
backgroundColor: immichBackgroundColor,
foregroundColor: Colors.indigo,
elevation: 1,
centerTitle: true,
surfaceTintColor: Colors.transparent,
),
bottomNavigationBarTheme: BottomNavigationBarThemeData(
type: BottomNavigationBarType.fixed,
backgroundColor: immichBackgroundColor,
selectedItemColor: Colors.indigo,
),
drawerTheme: DrawerThemeData(
backgroundColor: immichBackgroundColor,
),
textTheme: const TextTheme(
headline1: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Colors.indigo,
),
headline2: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
headline3: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Colors.indigo,
),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.indigo,
foregroundColor: Colors.white,
navigationBarTheme: NavigationBarThemeData(
indicatorColor: immichDarkThemePrimaryColor.withOpacity(0.4),
iconTheme: const MaterialStatePropertyAll(
IconThemeData(color: Colors.white),
),
backgroundColor: Colors.grey[900],
surfaceTintColor: Colors.transparent,
),
);

File diff suppressed because it is too large Load Diff