Skip to content

chore(mobile): small visual fix and update #17547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions mobile/assets/i18n/en-US.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"open": "Open",
"action_common_back": "Back",
"action_common_cancel": "Cancel",
"action_common_clear": "Clear",
Expand Down Expand Up @@ -312,7 +313,7 @@
"home_page_delete_remote_err_local": "Local assets in delete remote selection, skipping",
"home_page_favorite_err_local": "Can not favorite local assets yet, skipping",
"home_page_favorite_err_partner": "Can not favorite partner assets yet, skipping",
"home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s).",
"home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album so that the timeline can populate photos and videos in it",
"home_page_share_err_local": "Can not share local assets via link, skipping",
"home_page_upload_err_limit": "Can only upload a maximum of 30 assets at a time, skipping",
"ignore_icloud_photos": "Ignore iCloud photos",
Expand Down Expand Up @@ -693,4 +694,4 @@
"viewer_unstack": "Un-Stack",
"wifi_name": "WiFi Name",
"your_wifi_name": "Your WiFi name"
}
}
25 changes: 25 additions & 0 deletions mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,25 @@ PODS:
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- sqlite3 (3.49.1):
- sqlite3/common (= 3.49.1)
- sqlite3/common (3.49.1)
- sqlite3/dbstatvtab (3.49.1):
- sqlite3/common
- sqlite3/fts5 (3.49.1):
- sqlite3/common
- sqlite3/perf-threadsafe (3.49.1):
- sqlite3/common
- sqlite3/rtree (3.49.1):
- sqlite3/common
- sqlite3_flutter_libs (0.0.1):
- Flutter
- FlutterMacOS
- sqlite3 (~> 3.49.1)
- sqlite3/dbstatvtab
- sqlite3/fts5
- sqlite3/perf-threadsafe
- sqlite3/rtree
- SwiftyGif (5.4.5)
- url_launcher_ios (0.0.1):
- Flutter
Expand Down Expand Up @@ -130,6 +149,7 @@ DEPENDENCIES:
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)

Expand All @@ -140,6 +160,7 @@ SPEC REPOS:
- MapLibre
- SAMKeychain
- SDWebImage
- sqlite3
- SwiftyGif

EXTERNAL SOURCES:
Expand Down Expand Up @@ -195,6 +216,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
sqlite3_flutter_libs:
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
wakelock_plus:
Expand Down Expand Up @@ -232,6 +255,8 @@ SPEC CHECKSUMS:
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983
sqlite3_flutter_libs: f8fc13346870e73fe35ebf6dbb997fbcd156b241
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49
Expand Down
5 changes: 2 additions & 3 deletions mobile/lib/pages/backup/backup_album_selection.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'package:immich_mobile/services/app_settings.service.dart';
import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart';
import 'package:immich_mobile/widgets/backup/album_info_card.dart';
import 'package:immich_mobile/widgets/backup/album_info_list_tile.dart';
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart';

@RoutePage()
Expand All @@ -37,7 +36,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
if (albums.isEmpty) {
return const SliverToBoxAdapter(
child: Center(
child: ImmichLoadingIndicator(),
child: CircularProgressIndicator(),
),
);
}
Expand All @@ -61,7 +60,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
if (albums.isEmpty) {
return const SliverToBoxAdapter(
child: Center(
child: ImmichLoadingIndicator(),
child: CircularProgressIndicator(),
),
);
}
Expand Down
31 changes: 16 additions & 15 deletions mobile/lib/pages/photos/photos.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,28 +53,29 @@ class PhotosPage extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 16.0),
child: Text(
'home_page_building_timeline',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
style: context.textTheme.titleMedium?.copyWith(
color: context.primaryColor,
),
).tr(),
),
const SizedBox(height: 8),
AnimatedOpacity(
duration: const Duration(milliseconds: 500),
duration: const Duration(milliseconds: 1000),
opacity: tipOneOpacity.value,
child: SizedBox(
width: 250,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: const Text(
'home_page_first_time_notice',
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 12,
child: Column(
children: [
SizedBox(
width: 320,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
'home_page_first_time_notice',
textAlign: TextAlign.center,
style: context.textTheme.bodyMedium,
).tr(),
),
).tr(),
),
),
],
),
),
],
Expand Down
2 changes: 1 addition & 1 deletion mobile/lib/pages/search/search.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ class SearchPage extends HookConsumerWidget {
),
if (isSearching.value)
const Expanded(
child: Center(child: CircularProgressIndicator.adaptive()),
child: Center(child: CircularProgressIndicator()),
)
else
SearchResultGrid(
Expand Down
7 changes: 7 additions & 0 deletions mobile/lib/theme/theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,13 @@ ThemeData getThemeData({
),
),
dialogTheme: DialogThemeData(backgroundColor: colorScheme.surfaceContainer),
progressIndicatorTheme: const ProgressIndicatorThemeData(
// ignore: deprecated_member_use
year2023: false,
// TODO: Uncommented after upgrade to version later than 3.29.2
// circularTrackColor: Colors.black12,
trackGap: 3,
),
);
}

Expand Down
3 changes: 1 addition & 2 deletions mobile/lib/widgets/asset_grid/multiselect_grid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import 'package:immich_mobile/entities/album.entity.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/providers/asset.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:immich_mobile/utils/immich_loading_overlay.dart';
import 'package:immich_mobile/utils/selection_handlers.dart';
Expand Down Expand Up @@ -59,7 +58,7 @@ class MultiselectGrid extends HookConsumerWidget {
final bool editEnabled;
final Widget? emptyIndicator;
Widget buildDefaultLoadingIndicator() =>
const Center(child: ImmichLoadingIndicator());
const Center(child: CircularProgressIndicator());

Widget buildEmptyIndicator() =>
emptyIndicator ?? Center(child: const Text("no_assets_to_show").tr());
Expand Down
112 changes: 102 additions & 10 deletions mobile/lib/widgets/common/immich_loading_indicator.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:immich_mobile/widgets/common/immich_logo.dart';

class ImmichLoadingIndicator extends StatelessWidget {
class ImmichLoadingIndicator extends HookWidget {
final double? borderRadius;

const ImmichLoadingIndicator({
Expand All @@ -11,18 +12,109 @@ class ImmichLoadingIndicator extends StatelessWidget {

@override
Widget build(BuildContext context) {
final logoAnimationController = useAnimationController(
duration: const Duration(seconds: 6),
)
..reverse()
..repeat();

final borderAnimationController = useAnimationController(
duration: const Duration(seconds: 6),
)..repeat();

return Container(
height: 60,
width: 60,
height: 80,
width: 80,
decoration: BoxDecoration(
color: context.primaryColor.withAlpha(200),
borderRadius: BorderRadius.circular(borderRadius ?? 10),
color: Colors.transparent,
borderRadius: BorderRadius.circular(borderRadius ?? 50),
backgroundBlendMode: BlendMode.luminosity,
),
padding: const EdgeInsets.all(15),
child: const CircularProgressIndicator(
color: Colors.white,
strokeWidth: 3,
child: AnimatedBuilder(
animation: borderAnimationController,
builder: (context, child) {
return CustomPaint(
painter: GradientBorderPainter(
animation: borderAnimationController.value,
strokeWidth: 3,
),
child: child,
);
},
child: Padding(
padding: const EdgeInsets.all(15),
child: RotationTransition(
turns: logoAnimationController,
child: const ImmichLogo(
heroTag: 'logo',
),
),
),
),
);
}
}

class GradientBorderPainter extends CustomPainter {
final double animation;
final double strokeWidth;
final double opacity = 0.7;
final colors = [
const Color(0xFFFA2921),
const Color(0xFFED79B5),
const Color(0xFFFFB400),
const Color(0xFF1E83F7),
const Color(0xFF18C249),
];

GradientBorderPainter({
required this.animation,
required this.strokeWidth,
});

@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final radius = min(size.width, size.height) / 2 - strokeWidth / 2;

// Create a sweep gradient that covers the entire circle
final Rect rect = Rect.fromCircle(center: center, radius: radius);

// Create a paint with the gradient
final paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth;

// Create a gradient that smoothly transitions between colors
final shader = SweepGradient(
// Use a fixed starting point and let matrix transformation handle rotation
startAngle: 0,
endAngle: 2 * 3.14159,
colors: [
// Repeat colors to ensure smooth transitions
...colors.map((c) => c.withValues(alpha: opacity)),
colors.first.withValues(alpha: opacity),
],
// Add evenly distributed stops
stops: List.generate(
colors.length + 1,
(index) => index / colors.length,
),
tileMode: TileMode.clamp,
// Use transformations to rotate the gradient
transform: GradientRotation(-animation * 2 * 3.14159),
).createShader(rect);

paint.shader = shader;

// Draw the circular border
canvas.drawCircle(center, radius, paint);
}

@override
bool shouldRepaint(GradientBorderPainter oldDelegate) {
return animation != oldDelegate.animation;
}

double min(double a, double b) => a < b ? a : b;
}
2 changes: 1 addition & 1 deletion mobile/lib/widgets/forms/login/login_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ class LoginForm extends HookConsumerWidget {
),
onPressed: () => context.pushRoute(const SettingsRoute()),
icon: const Icon(Icons.settings_rounded),
label: const SizedBox.shrink(),
label: const Text(""),
),
),
const SizedBox(width: 1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import 'package:immich_mobile/widgets/settings/settings_button_list_tile.dart';
import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart';
import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart';
import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart';
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';

class BackupSettings extends HookConsumerWidget {
const BackupSettings({
Expand Down Expand Up @@ -59,7 +58,7 @@ class BackupSettings extends HookConsumerWidget {
? const Column(
children: [
SizedBox(height: 20),
Center(child: ImmichLoadingIndicator()),
Center(child: CircularProgressIndicator()),
SizedBox(height: 20),
],
)
Expand All @@ -83,9 +82,7 @@ class BackupSettings extends HookConsumerWidget {
),
buttonText: 'sync_albums'.tr(),
child: isAlbumSyncInProgress.value
? const CircularProgressIndicator.adaptive(
strokeWidth: 2,
)
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: syncAlbums,
child: Text('sync'.tr()),
Expand Down
8 changes: 8 additions & 0 deletions mobile/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.0"
punycode:
dependency: "direct main"
description:
name: punycode
sha256: "39b874cc1f78b94e57db17e74b3f2ba2a96e25c0bebdcc8a571614dccda0ff0c"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
recase:
dependency: transitive
description:
Expand Down