1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-03-01 15:11:21 +01: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 uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.3.10" flutter-version: "3.7.3"
cache: true cache: true
- name: Create the Keystore - name: Create the Keystore

View file

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

View file

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

View file

@ -2,6 +2,11 @@
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<application android:label="Immich" android:name=".ImmichApp" android:usesCleartextTraffic="true" <application android:label="Immich" android:name=".ImmichApp" android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher" android:requestLegacyExternalStorage="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" <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop"
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" 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(); await ImmichTestHelper.initialize();
group("Login input validation test", () { 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.waitForLoginScreen();
await helper.loginHelper.acknowledgeNewServerVersion(); await helper.loginHelper.acknowledgeNewServerVersion();
@ -17,15 +18,21 @@ void main() async {
await tester.pump(const Duration(milliseconds: 300)); 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( await helper.loginHelper.enterCredentials(
email: "demo@immich.app ", email: "demo@immich.app ",
); );
await tester.pump(const Duration(milliseconds: 300)); 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 { immichWidgetTest("Test invalid email", (tester, helper) async {
@ -33,13 +40,12 @@ void main() async {
await helper.loginHelper.acknowledgeNewServerVersion(); await helper.loginHelper.acknowledgeNewServerVersion();
await helper.loginHelper.enterCredentials( await helper.loginHelper.enterCredentials(
email: "demo.immich.app", email: "demo.immich.app",
); );
await tester.pump(const Duration(milliseconds: 300)); await tester.pump(const Duration(milliseconds: 300));
expect(find.text("login_form_err_invalid_email".tr()), findsOneWidget); 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 # 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. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@ -34,19 +34,8 @@ target 'Runner' do
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end end
# post_install do |installer| post_install do |installer|
# installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
# flutter_additional_ios_build_settings(target) flutter_additional_ios_build_settings(target)
# end end
# 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

View file

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

View file

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 51; objectVersion = 54;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@ -201,6 +201,7 @@
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
@ -237,6 +238,7 @@
}; };
9740EEB61CF901F6004384FC /* Run Script */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
@ -341,7 +343,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
NEW_SETTING = ""; NEW_SETTING = "";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -425,7 +427,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
NEW_SETTING = ""; NEW_SETTING = "";
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
@ -475,7 +477,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
NEW_SETTING = ""; NEW_SETTING = "";
SDKROOT = iphoneos; 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"?> <?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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Immich</string> <string>Immich</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>immich_mobile</string> <string>immich_mobile</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.46.0</string> <string>1.46.0</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>85</string> <string>85</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true />
<key>MGLMapboxMetricsEnabledSettingShownInApp</key> <key>MGLMapboxMetricsEnabledSettingShownInApp</key>
<true/> <true />
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
<true/> <true />
</dict> </dict>
<key>NSLocationAlwaysUsageDescription</key> <key>NSLocationAlwaysUsageDescription</key>
<string>Enable location setting to show position of assets on map</string> <string>Enable location setting to show position of assets on map</string>
<key>NSLocationWhenInUseUsageDescription</key> <key>NSLocationWhenInUseUsageDescription</key>
<string>Enable location setting to show position of assets on map</string> <string>Enable location setting to show position of assets on map</string>
<key>NSPhotoLibraryUsageDescription</key> <key>NSPhotoLibraryUsageDescription</key>
<string>We need to manage backup your photos album</string> <string>We need to manage backup your photos album</string>
<key>NSPhotoLibraryAddUsageDescription</key> <key>NSPhotoLibraryAddUsageDescription</key>
<string>We need to manage backup your photos album</string> <string>We need to manage backup your photos album</string>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>We need to access the camera to let you take beautiful video using this app</string> <string>We need to access the camera to let you take beautiful video using this app</string>
<key>NSMicrophoneUsageDescription</key> <key>NSMicrophoneUsageDescription</key>
<string>We need to access the microphone to let you take beautiful video using this app</string> <string>We need to access the microphone to let you take beautiful video using this app</string>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>
<string>Main</string> <string>Main</string>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UISupportedInterfaceOrientations~ipad</key> <key>UISupportedInterfaceOrientations~ipad</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<true/> <true />
<key>io.flutter.embedded_views_preview</key> <key>io.flutter.embedded_views_preview</key>
<true/> <true />
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false />
<key>CADisableMinimumFrameDurationOnPhone</key> <key>CADisableMinimumFrameDurationOnPhone</key>
<true/> <true />
<key>LSApplicationQueriesSchemes</key> <key>LSApplicationQueriesSchemes</key>
<array> <array>
<string>https</string> <string>https</string>
</array> </array>
<key>CFBundleLocalizations</key> <key>CFBundleLocalizations</key>
<array> <array>
<string>cs</string> <string>cs</string>
<string>da</string> <string>da</string>
<string>de</string> <string>de</string>
<string>en</string> <string>en</string>
<string>es</string> <string>es</string>
<string>fi</string> <string>fi</string>
<string>fr</string> <string>fr</string>
<string>it</string> <string>it</string>
<string>ja</string> <string>ja</string>
<string>ko</string> <string>ko</string>
<string>nl</string> <string>nl</string>
<string>pl</string> <string>pl</string>
<string>pt</string> <string>pt</string>
<string>ru</string> <string>ru</string>
<string>sk</string> <string>sk</string>
<string>zh</string> <string>zh</string>
</array> </array>
<key>UIStatusBarHidden</key> <key>UIStatusBarHidden</key>
<false/> <false />
</dict> <key>UIApplicationSupportsIndirectInputEvents</key>
</plist> <true />
<key>FLTEnableImpeller</key>
<true />
</dict>
</plist>

View file

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

View file

@ -24,90 +24,97 @@ class AlbumThumbnailCard extends StatelessWidget {
var isDarkMode = Theme.of(context).brightness == Brightness.dark; var isDarkMode = Theme.of(context).brightness == Brightness.dark;
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
var cardSize = constraints.maxWidth; var cardSize = constraints.maxWidth;
buildEmptyThumbnail() { buildEmptyThumbnail() {
return Container( return Container(
height: cardSize, height: cardSize,
width: cardSize, width: cardSize,
decoration: BoxDecoration( decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[200], color: isDarkMode ? Colors.grey[800] : Colors.grey[200],
),
child: Center(
child: Icon(
Icons.no_photography,
size: cardSize * .15,
), ),
), child: Center(
); child: Icon(
} Icons.no_photography,
size: cardSize * .15,
),
),
);
}
buildAlbumThumbnail() { buildAlbumThumbnail() {
return CachedNetworkImage( return CachedNetworkImage(
width: cardSize, width: cardSize,
height: cardSize, height: cardSize,
fit: BoxFit.cover, fit: BoxFit.cover,
fadeInDuration: const Duration(milliseconds: 200), fadeInDuration: const Duration(milliseconds: 200),
imageUrl: getAlbumThumbnailUrl( imageUrl: getAlbumThumbnailUrl(
album, album,
type: ThumbnailFormat.JPEG, type: ThumbnailFormat.JPEG,
), ),
httpHeaders: {"Authorization": "Bearer ${box.get(accessTokenKey)}"}, httpHeaders: {"Authorization": "Bearer ${box.get(accessTokenKey)}"},
cacheKey: getAlbumThumbNailCacheKey(album, type: ThumbnailFormat.JPEG), cacheKey:
); getAlbumThumbNailCacheKey(album, type: ThumbnailFormat.JPEG),
} );
}
return GestureDetector( return GestureDetector(
onTap: onTap, onTap: onTap,
child: Padding( child: Flex(
padding: const EdgeInsets.only(bottom: 32.0), direction: Axis.vertical,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Flexible(
child: ClipRRect( child: Column(
borderRadius: BorderRadius.circular(8), crossAxisAlignment: CrossAxisAlignment.start,
child: album.albumThumbnailAssetId == null children: [
? buildEmptyThumbnail() SizedBox(
: buildAlbumThumbnail(), width: cardSize,
), height: cardSize,
), child: ClipRRect(
Padding( borderRadius: BorderRadius.circular(20),
padding: const EdgeInsets.only(top: 8.0), child: album.albumThumbnailAssetId == null
child: SizedBox( ? buildEmptyThumbnail()
width: cardSize, : buildAlbumThumbnail(),
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() ),
], 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, focusNode: albumTitleTextFieldFocusNode,
style: TextStyle( style: TextStyle(
fontSize: 28, fontSize: 28,
color: Colors.grey[700], color: isDarkTheme ? Colors.grey[300] : Colors.grey[700],
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
controller: albumTitleController, controller: albumTitleController,

View file

@ -19,7 +19,7 @@ class CreateAlbumPage extends HookConsumerWidget {
final List<Asset>? initialAssets; final List<Asset>? initialAssets;
const CreateAlbumPage({ const CreateAlbumPage({
Key? key, Key? key,
required this.isSharedAlbum, required this.isSharedAlbum,
this.initialAssets, this.initialAssets,
}) : super(key: key); }) : super(key: key);
@ -84,7 +84,7 @@ class CreateAlbumPage extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 200, left: 18), padding: const EdgeInsets.only(top: 200, left: 18),
child: Text( child: Text(
'create_shared_album_page_share_add_assets', 'create_shared_album_page_share_add_assets',
style: Theme.of(context).textTheme.headline2?.copyWith( style: Theme.of(context).textTheme.displayMedium?.copyWith(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
), ),
@ -214,7 +214,7 @@ class CreateAlbumPage extends HookConsumerWidget {
), ),
title: Text( title: Text(
'share_create_album', 'share_create_album',
style: Theme.of(context).textTheme.headline2?.copyWith( style: Theme.of(context).textTheme.displayMedium?.copyWith(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
), ),
).tr(), ).tr(),
@ -228,7 +228,9 @@ class CreateAlbumPage extends HookConsumerWidget {
'create_shared_album_page_share'.tr(), 'create_shared_album_page_share'.tr(),
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, 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 @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final albums = ref.watch(albumProvider); final albums = ref.watch(albumProvider);
var isDarkMode = Theme.of(context).brightness == Brightness.dark;
useEffect( useEffect(
() { () {
@ -122,9 +123,12 @@ class LibraryPage extends HookConsumerWidget {
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( 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: Center(
child: Icon( child: Icon(
@ -168,25 +172,22 @@ class LibraryPage extends HookConsumerWidget {
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 12.0, fontSize: 12.0,
color: Theme.of(context).brightness == Brightness.dark color: isDarkMode ? Colors.white : Colors.black,
? Colors.white
: Colors.black,
), ),
), ),
), ),
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.grey[50],
side: BorderSide( side: BorderSide(
color: Theme.of(context).brightness == Brightness.dark color: isDarkMode ? Colors.grey[800]! : Colors.grey[300]!,
? Colors.grey[600]!
: Colors.grey[300]!,
), ),
alignment: Alignment.centerLeft, 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( delegate: SliverChildBuilderDelegate(
childCount: sorted.length + 1, childCount: sorted.length + 1,
(context, index) { (context, index) {
if (index == 0) { if (index == 0) {
return buildCreateAlbumButton(); return buildCreateAlbumButton();
} }

View file

@ -77,13 +77,13 @@ class SharingPage extends HookConsumerWidget {
child: Card( child: Card(
elevation: 0, elevation: 0,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), // if you need this borderRadius: BorderRadius.circular(20),
side: const BorderSide( side: const BorderSide(
color: Colors.grey, color: Colors.grey,
width: 1, width: 0.5,
), ),
), ),
color: Colors.transparent, // color: Colors.transparent,
child: Padding( child: Padding(
padding: const EdgeInsets.all(18.0), padding: const EdgeInsets.all(18.0),
child: Column( child: Column(
@ -92,7 +92,7 @@ class SharingPage extends HookConsumerWidget {
Padding( Padding(
padding: const EdgeInsets.only(left: 5.0, bottom: 5), padding: const EdgeInsets.only(left: 5.0, bottom: 5),
child: Icon( child: Icon(
Icons.offline_share_outlined, Icons.insert_photo_rounded,
size: 50, size: 50,
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
), ),
@ -101,7 +101,7 @@ class SharingPage extends HookConsumerWidget {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
'sharing_page_empty_list', 'sharing_page_empty_list',
style: Theme.of(context).textTheme.headline3, style: Theme.of(context).textTheme.displaySmall,
).tr(), ).tr(),
), ),
Padding( 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/asset_viewer/views/video_viewer_page.dart';
import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart'; import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart';
import 'package:immich_mobile/shared/services/asset.service.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/providers/app_settings.provider.dart';
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart'; import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
import 'package:immich_mobile/shared/ui/photo_view/photo_view_gallery.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) { void handleSwipeUpDown(DragUpdateDetails details) {
int sensitivity = 15; int sensitivity = 15;
int dxThreshhold = 50; int dxThreshold = 50;
if (isZoomed.value) { if (isZoomed.value) {
return; return;
@ -222,7 +222,7 @@ class GalleryViewerPage extends HookConsumerWidget {
// Check for delta from initial down point // Check for delta from initial down point
final d = details.localPosition - localPosition; final d = details.localPosition - localPosition;
// If the magnitude of the dx swipe is large, we probably didn't mean to go down // 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; return;
} }
@ -247,8 +247,8 @@ class GalleryViewerPage extends HookConsumerWidget {
isPlayingMotionVideo: isPlayingMotionVideo.value, isPlayingMotionVideo: isPlayingMotionVideo.value,
asset: assetList[indexOfAsset.value], asset: assetList[indexOfAsset.value],
isFavorite: ref.watch(favoriteProvider).contains( isFavorite: ref.watch(favoriteProvider).contains(
assetList[indexOfAsset.value].id, assetList[indexOfAsset.value].id,
), ),
onMoreInfoPressed: () { onMoreInfoPressed: () {
showInfo(); showInfo();
}, },
@ -314,7 +314,7 @@ class GalleryViewerPage extends HookConsumerWidget {
? (context, event) { ? (context, event) {
final asset = assetList[indexOfAsset.value]; final asset = assetList[indexOfAsset.value];
if (!asset.isLocal) { 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) // Three-Stage Loading (WEBP -> JPEG -> Original)
final webPThumbnail = CachedNetworkImage( final webPThumbnail = CachedNetworkImage(
imageUrl: getThumbnailUrl( imageUrl: getThumbnailUrl(

View file

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

View file

@ -92,11 +92,10 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
RenderAssetGridRow row, RenderAssetGridRow row,
bool scrolling, bool scrolling,
) { ) {
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
final size = constraints.maxWidth / widget.assetsPerRow - final size = constraints.maxWidth / widget.assetsPerRow -
widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow; widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow;
return Row( return Row(
key: Key("asset-row-${row.assets.first.id}"), key: Key("asset-row-${row.assets.first.id}"),
children: row.assets.mapIndexed((int index, Asset asset) { children: row.assets.mapIndexed((int index, Asset asset) {
@ -141,7 +140,7 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
style: TextStyle( style: TextStyle(
fontSize: 26, fontSize: 26,
fontWeight: FontWeight.bold, 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( style: TextStyle(
fontSize: 26, fontSize: 26,
fontWeight: FontWeight.bold, 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:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.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/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/ui/drag_sheet.dart';
import 'package:immich_mobile/shared/models/album.dart'; import 'package:immich_mobile/shared/models/album.dart';
@ -29,6 +29,8 @@ class ControlBottomAppBar extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
var isDarkMode = Theme.of(context).brightness == Brightness.dark;
Widget renderActionButtons() { Widget renderActionButtons() {
return Row( return Row(
children: [ children: [
@ -60,7 +62,6 @@ class ControlBottomAppBar extends ConsumerWidget {
); );
}, },
), ),
], ],
); );
} }
@ -75,7 +76,9 @@ class ControlBottomAppBar extends ConsumerWidget {
ScrollController scrollController, ScrollController scrollController,
) { ) {
return Card( return Card(
elevation: 12.0, color: isDarkMode ? Colors.grey[900] : Colors.grey[100],
surfaceTintColor: Colors.transparent,
elevation: 18.0,
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(12), topLeft: Radius.circular(12),
@ -83,45 +86,37 @@ class ControlBottomAppBar extends ConsumerWidget {
), ),
), ),
margin: const EdgeInsets.all(0), margin: const EdgeInsets.all(0),
child: Container( child: CustomScrollView(
decoration: const BoxDecoration( controller: scrollController,
borderRadius: BorderRadius.only( slivers: [
topLeft: Radius.circular(12), SliverToBoxAdapter(
topRight: Radius.circular(12), 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(
child: CustomScrollView( padding: const EdgeInsets.symmetric(horizontal: 16),
controller: scrollController, sliver: AddToAlbumSliverList(
slivers: [ albums: albums,
SliverToBoxAdapter( sharedAlbums: sharedAlbums,
child: Column( onAddToAlbum: onAddToAlbum,
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), const SliverToBoxAdapter(
sliver: AddToAlbumSliverList( child: SizedBox(height: 200),
albums: albums, )
sharedAlbums: sharedAlbums, ],
onAddToAlbum: onAddToAlbum,
),
),
const SliverToBoxAdapter(
child: SizedBox(height: 200),
)
],
),
), ),
); );
}, },

View file

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

View file

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

View file

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

View file

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

View file

@ -11,7 +11,6 @@ class TabControllerPage extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
navigationRail(TabsRouter tabsRouter) { navigationRail(TabsRouter tabsRouter) {
return NavigationRail( return NavigationRail(
labelType: NavigationRailLabelType.all, labelType: NavigationRailLabelType.all,
@ -35,32 +34,33 @@ class TabControllerPage extends ConsumerWidget {
right: 4, right: 4,
bottom: 4, bottom: 4,
), ),
icon: const Icon(Icons.photo_outlined), icon: const Icon(Icons.photo_outlined),
selectedIcon: const Icon(Icons.photo), selectedIcon: const Icon(Icons.photo),
label: const Text('tab_controller_nav_photos').tr(), label: const Text('tab_controller_nav_photos').tr(),
), ),
NavigationRailDestination( NavigationRailDestination(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
icon: const Icon(Icons.search_rounded), icon: const Icon(Icons.search_rounded),
selectedIcon: const Icon(Icons.search), selectedIcon: const Icon(Icons.search),
label: const Text('tab_controller_nav_search').tr(), label: const Text('tab_controller_nav_search').tr(),
), ),
NavigationRailDestination( NavigationRailDestination(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
icon: const Icon(Icons.share_rounded), icon: const Icon(Icons.share_rounded),
selectedIcon: const Icon(Icons.share), selectedIcon: const Icon(Icons.share),
label: const Text('tab_controller_nav_sharing').tr(), label: const Text('tab_controller_nav_sharing').tr(),
), ),
NavigationRailDestination( NavigationRailDestination(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
icon: const Icon(Icons.photo_album_outlined), icon: const Icon(Icons.photo_album_outlined),
selectedIcon: const Icon(Icons.photo_album), selectedIcon: const Icon(Icons.photo_album),
label: const Text('tab_controller_nav_library').tr(), label: const Text('tab_controller_nav_library').tr(),
), ),
], ],
); );
} }
// ignore: unused_element
bottomNavigationBar(TabsRouter tabsRouter) { bottomNavigationBar(TabsRouter tabsRouter) {
return BottomNavigationBar( return BottomNavigationBar(
selectedLabelStyle: const TextStyle( 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); final multiselectEnabled = ref.watch(multiselectProvider);
return AutoTabsRouter( return AutoTabsRouter(
routes: [ routes: [
@ -116,7 +168,7 @@ class TabControllerPage extends ConsumerWidget {
bool atHomeTab = tabsRouter.activeIndex == 0; bool atHomeTab = tabsRouter.activeIndex == 0;
if (!atHomeTab) { if (!atHomeTab) {
tabsRouter.setActiveIndex(0); tabsRouter.setActiveIndex(0);
} }
return atHomeTab; return atHomeTab;
}, },
@ -127,7 +179,7 @@ class TabControllerPage extends ConsumerWidget {
final Widget body; final Widget body;
if (constraints.maxWidth < medium) { if (constraints.maxWidth < medium) {
// Normal phone width // Normal phone width
bottom = bottomNavigationBar(tabsRouter); bottom = experimentalNavigationBar(tabsRouter);
body = FadeTransition( body = FadeTransition(
opacity: animation, opacity: animation,
child: child, child: child,
@ -146,13 +198,13 @@ class TabControllerPage extends ConsumerWidget {
), ),
], ],
); );
} return Scaffold( }
body: body, return Scaffold(
bottomNavigationBar: multiselectEnabled body: body,
? null bottomNavigationBar: multiselectEnabled ? null : bottom,
: 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( ThemeData immichDarkTheme = ThemeData(
useMaterial3: true, useMaterial3: true,
brightness: Brightness.dark, brightness: Brightness.dark,
@ -43,7 +120,8 @@ ThemeData immichDarkTheme = ThemeData(
), ),
backgroundColor: const Color.fromARGB(255, 32, 33, 35), backgroundColor: const Color.fromARGB(255, 32, 33, 35),
foregroundColor: immichDarkThemePrimaryColor, foregroundColor: immichDarkThemePrimaryColor,
elevation: 1, elevation: 0,
scrolledUnderElevation: 0,
centerTitle: true, centerTitle: true,
), ),
bottomNavigationBarTheme: BottomNavigationBarThemeData( bottomNavigationBarTheme: BottomNavigationBarThemeData(
@ -56,17 +134,17 @@ ThemeData immichDarkTheme = ThemeData(
scrimColor: Colors.white.withOpacity(0.1), scrimColor: Colors.white.withOpacity(0.1),
), ),
textTheme: TextTheme( textTheme: TextTheme(
headline1: const TextStyle( displayLarge: const TextStyle(
fontSize: 26, fontSize: 26,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 255, 255, 255), color: Color.fromARGB(255, 255, 255, 255),
), ),
headline2: const TextStyle( displayMedium: const TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 255, 255, 255), color: Color.fromARGB(255, 255, 255, 255),
), ),
headline3: TextStyle( displaySmall: TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: immichDarkThemePrimaryColor, color: immichDarkThemePrimaryColor,
@ -79,57 +157,19 @@ ThemeData immichDarkTheme = ThemeData(
backgroundColor: immichDarkThemePrimaryColor, backgroundColor: immichDarkThemePrimaryColor,
), ),
), ),
); chipTheme: base.chipTheme,
popupMenuTheme: const PopupMenuThemeData(
ThemeData immichLightTheme = ThemeData( shape: RoundedRectangleBorder(
useMaterial3: true, borderRadius: BorderRadius.all(Radius.circular(10)),
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,
), ),
backgroundColor: immichBackgroundColor, surfaceTintColor: Colors.transparent,
foregroundColor: Colors.indigo,
elevation: 1,
centerTitle: true,
), ),
bottomNavigationBarTheme: BottomNavigationBarThemeData( navigationBarTheme: NavigationBarThemeData(
type: BottomNavigationBarType.fixed, indicatorColor: immichDarkThemePrimaryColor.withOpacity(0.4),
backgroundColor: immichBackgroundColor, iconTheme: const MaterialStatePropertyAll(
selectedItemColor: Colors.indigo, IconThemeData(color: Colors.white),
),
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,
), ),
backgroundColor: Colors.grey[900],
surfaceTintColor: Colors.transparent,
), ),
); );

File diff suppressed because it is too large Load diff