mirror of
https://github.com/immich-app/immich.git
synced 2025-12-10 15:15:22 -05:00
Merge branch 'main' into fix/save-album-sort
This commit is contained in:
commit
aa0732158b
5
.github/workflows/static_analysis.yml
vendored
5
.github/workflows/static_analysis.yml
vendored
@ -100,8 +100,9 @@ jobs:
|
|||||||
- name: Run dart format
|
- name: Run dart format
|
||||||
run: make format
|
run: make format
|
||||||
|
|
||||||
- name: Run dart custom_lint
|
# TODO: Re-enable after upgrading custom_lint
|
||||||
run: dart run custom_lint
|
# - name: Run dart custom_lint
|
||||||
|
# run: dart run custom_lint
|
||||||
|
|
||||||
# TODO: Use https://github.com/CQLabs/dcm-action
|
# TODO: Use https://github.com/CQLabs/dcm-action
|
||||||
- name: Run DCM
|
- name: Run DCM
|
||||||
|
|||||||
@ -4,3 +4,4 @@
|
|||||||
/web/ @danieldietzler
|
/web/ @danieldietzler
|
||||||
/machine-learning/ @mertalev
|
/machine-learning/ @mertalev
|
||||||
/e2e/ @danieldietzler
|
/e2e/ @danieldietzler
|
||||||
|
/mobile/ @shenlong-tanwen
|
||||||
|
|||||||
@ -3,7 +3,7 @@ version = "3.8.2"
|
|||||||
backend = "asdf:dart"
|
backend = "asdf:dart"
|
||||||
|
|
||||||
[tools.flutter]
|
[tools.flutter]
|
||||||
version = "3.32.8-stable"
|
version = "3.35.3-stable"
|
||||||
backend = "asdf:flutter"
|
backend = "asdf:flutter"
|
||||||
|
|
||||||
[tools."github:CQLabs/homebrew-dcm"]
|
[tools."github:CQLabs/homebrew-dcm"]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[tools]
|
[tools]
|
||||||
node = "22.19.0"
|
node = "22.19.0"
|
||||||
flutter = "3.32.8"
|
flutter = "3.35.3"
|
||||||
pnpm = "10.14.0"
|
pnpm = "10.14.0"
|
||||||
dart = "3.8.2"
|
dart = "3.8.2"
|
||||||
|
|
||||||
@ -300,7 +300,7 @@ run = "tsc --noEmit"
|
|||||||
depends = "web:svelte-kit-sync"
|
depends = "web:svelte-kit-sync"
|
||||||
env._.path = "web/node_modules/.bin"
|
env._.path = "web/node_modules/.bin"
|
||||||
dir = "web"
|
dir = "web"
|
||||||
run = "svelte-check --no-tsconfig --fail-on-warnings --compiler-warnings 'reactive_declaration_non_reactive_property:ignore' --ignore src/lib/components/timeline/Timeline.svelte"
|
run = "svelte-check --no-tsconfig --fail-on-warnings"
|
||||||
|
|
||||||
[tasks."web:checklist"]
|
[tasks."web:checklist"]
|
||||||
run = [
|
run = [
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"flutter": "3.32.8"
|
"flutter": "3.35.3"
|
||||||
}
|
}
|
||||||
4
mobile/.vscode/settings.json
vendored
4
mobile/.vscode/settings.json
vendored
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"dart.flutterSdkPath": ".fvm/versions/3.32.8",
|
"dart.flutterSdkPath": ".fvm/versions/3.35.3",
|
||||||
"dart.lineLength": 120,
|
"dart.lineLength": 120,
|
||||||
"[dart]": {
|
"[dart]": {
|
||||||
"editor.rulers": [120],
|
"editor.rulers": [120]
|
||||||
},
|
},
|
||||||
"search.exclude": {
|
"search.exclude": {
|
||||||
"**/.fvm": true
|
"**/.fvm": true
|
||||||
|
|||||||
@ -43,8 +43,9 @@ analyzer:
|
|||||||
- lib/**/*.g.dart
|
- lib/**/*.g.dart
|
||||||
- lib/**/*.drift.dart
|
- lib/**/*.drift.dart
|
||||||
|
|
||||||
plugins:
|
# TODO: Re-enable after upgrading custom_lint
|
||||||
- custom_lint
|
# plugins:
|
||||||
|
# - custom_lint
|
||||||
|
|
||||||
custom_lint:
|
custom_lint:
|
||||||
debug: true
|
debug: true
|
||||||
|
|||||||
@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>12.0</string>
|
<string>13.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@ -253,7 +253,7 @@ SPEC CHECKSUMS:
|
|||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
|
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
|
||||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||||
|
|||||||
@ -16,6 +16,7 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
|||||||
|
|
||||||
private static let refreshTaskID = "app.alextran.immich.background.refreshUpload"
|
private static let refreshTaskID = "app.alextran.immich.background.refreshUpload"
|
||||||
private static let processingTaskID = "app.alextran.immich.background.processingUpload"
|
private static let processingTaskID = "app.alextran.immich.background.processingUpload"
|
||||||
|
private static let taskSemaphore = DispatchSemaphore(value: 1)
|
||||||
|
|
||||||
public static func registerBackgroundWorkers() {
|
public static func registerBackgroundWorkers() {
|
||||||
BGTaskScheduler.shared.register(
|
BGTaskScheduler.shared.register(
|
||||||
@ -59,12 +60,18 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
|||||||
|
|
||||||
private static func handleBackgroundRefresh(task: BGAppRefreshTask) {
|
private static func handleBackgroundRefresh(task: BGAppRefreshTask) {
|
||||||
scheduleRefreshWorker()
|
scheduleRefreshWorker()
|
||||||
// Restrict the refresh task to run only for a maximum of (maxSeconds) seconds
|
// If another task is running, cede the background time back to the OS
|
||||||
runBackgroundWorker(task: task, taskType: .refresh, maxSeconds: 20)
|
if taskSemaphore.wait(timeout: .now()) == .success {
|
||||||
|
// Restrict the refresh task to run only for a maximum of (maxSeconds) seconds
|
||||||
|
runBackgroundWorker(task: task, taskType: .refresh, maxSeconds: 20)
|
||||||
|
} else {
|
||||||
|
task.setTaskCompleted(success: false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func handleBackgroundProcessing(task: BGProcessingTask) {
|
private static func handleBackgroundProcessing(task: BGProcessingTask) {
|
||||||
scheduleProcessingWorker()
|
scheduleProcessingWorker()
|
||||||
|
taskSemaphore.wait()
|
||||||
// There are no restrictions for processing tasks. Although, the OS could signal expiration at any time
|
// There are no restrictions for processing tasks. Although, the OS could signal expiration at any time
|
||||||
runBackgroundWorker(task: task, taskType: .processing, maxSeconds: nil)
|
runBackgroundWorker(task: task, taskType: .processing, maxSeconds: nil)
|
||||||
}
|
}
|
||||||
@ -80,6 +87,7 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
|||||||
* - maxSeconds: Optional timeout for the operation in seconds
|
* - maxSeconds: Optional timeout for the operation in seconds
|
||||||
*/
|
*/
|
||||||
private static func runBackgroundWorker(task: BGTask, taskType: BackgroundTaskType, maxSeconds: Int?) {
|
private static func runBackgroundWorker(task: BGTask, taskType: BackgroundTaskType, maxSeconds: Int?) {
|
||||||
|
defer { taskSemaphore.signal() }
|
||||||
let semaphore = DispatchSemaphore(value: 0)
|
let semaphore = DispatchSemaphore(value: 0)
|
||||||
var isSuccess = true
|
var isSuccess = true
|
||||||
|
|
||||||
|
|||||||
@ -169,7 +169,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
|||||||
album.activityEnabled = value;
|
album.activityEnabled = value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
activeColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor,
|
activeThumbColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text(
|
title: Text(
|
||||||
"comments_and_likes",
|
"comments_and_likes",
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -9,11 +11,13 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/backup/backup_toggle_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/backup/backup_toggle_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
|
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
import 'package:immich_mobile/widgets/backup/backup_info_card.dart';
|
import 'package:immich_mobile/widgets/backup/backup_info_card.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
@ -25,6 +29,8 @@ class DriftBackupPage extends ConsumerStatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
||||||
|
Timer? _countPoller;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -33,9 +39,42 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup)) {
|
||||||
|
_startCountPolling();
|
||||||
|
}
|
||||||
|
|
||||||
ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
|
ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _startCountPolling() {
|
||||||
|
_countPoller?.cancel();
|
||||||
|
_countPoller = Timer.periodic(const Duration(seconds: 5), (timer) async {
|
||||||
|
if (!mounted) {
|
||||||
|
timer.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final currentUser = ref.read(currentUserProvider);
|
||||||
|
if (currentUser == null) {
|
||||||
|
timer.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _stopCountPolling() {
|
||||||
|
_countPoller?.cancel();
|
||||||
|
_countPoller = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_stopCountPolling();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final selectedAlbum = ref
|
final selectedAlbum = ref
|
||||||
@ -55,10 +94,12 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
|||||||
await backgroundManager.syncRemote();
|
await backgroundManager.syncRemote();
|
||||||
await backupNotifier.getBackupStatus(currentUser.id);
|
await backupNotifier.getBackupStatus(currentUser.id);
|
||||||
await backupNotifier.startBackup(currentUser.id);
|
await backupNotifier.startBackup(currentUser.id);
|
||||||
|
_startCountPolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> stopBackup() async {
|
Future<void> stopBackup() async {
|
||||||
await backupNotifier.cancel();
|
await backupNotifier.cancel();
|
||||||
|
_stopCountPolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|||||||
@ -112,7 +112,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
|||||||
return SwitchListTile.adaptive(
|
return SwitchListTile.adaptive(
|
||||||
value: showMetadata.value,
|
value: showMetadata.value,
|
||||||
onChanged: newShareLink.value.isEmpty ? (value) => showMetadata.value = value : null,
|
onChanged: newShareLink.value.isEmpty ? (value) => showMetadata.value = value : null,
|
||||||
activeColor: colorScheme.primary,
|
activeThumbColor: colorScheme.primary,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text("show_metadata", style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(),
|
title: Text("show_metadata", style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(),
|
||||||
);
|
);
|
||||||
@ -122,7 +122,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
|||||||
return SwitchListTile.adaptive(
|
return SwitchListTile.adaptive(
|
||||||
value: allowDownload.value,
|
value: allowDownload.value,
|
||||||
onChanged: newShareLink.value.isEmpty ? (value) => allowDownload.value = value : null,
|
onChanged: newShareLink.value.isEmpty ? (value) => allowDownload.value = value : null,
|
||||||
activeColor: colorScheme.primary,
|
activeThumbColor: colorScheme.primary,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text(
|
title: Text(
|
||||||
"allow_public_user_to_download",
|
"allow_public_user_to_download",
|
||||||
@ -135,7 +135,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
|||||||
return SwitchListTile.adaptive(
|
return SwitchListTile.adaptive(
|
||||||
value: allowUpload.value,
|
value: allowUpload.value,
|
||||||
onChanged: newShareLink.value.isEmpty ? (value) => allowUpload.value = value : null,
|
onChanged: newShareLink.value.isEmpty ? (value) => allowUpload.value = value : null,
|
||||||
activeColor: colorScheme.primary,
|
activeThumbColor: colorScheme.primary,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text(
|
title: Text(
|
||||||
"allow_public_user_to_upload",
|
"allow_public_user_to_upload",
|
||||||
@ -148,7 +148,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
|||||||
return SwitchListTile.adaptive(
|
return SwitchListTile.adaptive(
|
||||||
value: editExpiry.value,
|
value: editExpiry.value,
|
||||||
onChanged: newShareLink.value.isEmpty ? (value) => editExpiry.value = value : null,
|
onChanged: newShareLink.value.isEmpty ? (value) => editExpiry.value = value : null,
|
||||||
activeColor: colorScheme.primary,
|
activeThumbColor: colorScheme.primary,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text(
|
title: Text(
|
||||||
"change_expiration_time",
|
"change_expiration_time",
|
||||||
|
|||||||
@ -208,7 +208,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
|
|||||||
activityEnabled.value = value;
|
activityEnabled.value = value;
|
||||||
await ref.read(remoteAlbumProvider.notifier).setActivityStatus(album.id, value);
|
await ref.read(remoteAlbumProvider.notifier).setActivityStatus(album.id, value);
|
||||||
},
|
},
|
||||||
activeColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor,
|
activeThumbColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text(
|
title: Text(
|
||||||
"comments_and_likes",
|
"comments_and_likes",
|
||||||
|
|||||||
@ -96,7 +96,7 @@ mixin CancellableImageProviderMixin<T extends Object> on CancellableImageProvide
|
|||||||
|
|
||||||
final operation = cachedOperation;
|
final operation = cachedOperation;
|
||||||
if (operation != null) {
|
if (operation != null) {
|
||||||
this.cachedOperation = null;
|
cachedOperation = null;
|
||||||
operation.cancel();
|
operation.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,8 +12,8 @@ import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart
|
|||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
import 'package:immich_mobile/services/upload.service.dart';
|
import 'package:immich_mobile/services/upload.service.dart';
|
||||||
import 'package:logging/logging.dart';
|
|
||||||
import 'package:immich_mobile/utils/debug_print.dart';
|
import 'package:immich_mobile/utils/debug_print.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
class EnqueueStatus {
|
class EnqueueStatus {
|
||||||
final int enqueueCount;
|
final int enqueueCount;
|
||||||
@ -234,10 +234,6 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
|||||||
|
|
||||||
switch (update.status) {
|
switch (update.status) {
|
||||||
case TaskStatus.complete:
|
case TaskStatus.complete:
|
||||||
if (update.task.group == kBackupGroup) {
|
|
||||||
state = state.copyWith(backupCount: state.backupCount + 1, remainderCount: state.remainderCount - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the completed task from the upload items
|
// Remove the completed task from the upload items
|
||||||
if (state.uploadItems.containsKey(taskId)) {
|
if (state.uploadItems.containsKey(taskId)) {
|
||||||
Future.delayed(const Duration(milliseconds: 1000), () {
|
Future.delayed(const Duration(milliseconds: 1000), () {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class MapSettingsListTile extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SwitchListTile.adaptive(
|
return SwitchListTile.adaptive(
|
||||||
activeColor: context.primaryColor,
|
activeThumbColor: context.primaryColor,
|
||||||
title: Text(title, style: context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(),
|
title: Text(title, style: context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(),
|
||||||
value: selected,
|
value: selected,
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
|
|||||||
@ -350,8 +350,8 @@ class PhotoViewCoreState extends State<PhotoViewCore>
|
|||||||
final computedScale = useImageScale ? 1.0 : scale;
|
final computedScale = useImageScale ? 1.0 : scale;
|
||||||
|
|
||||||
final matrix = Matrix4.identity()
|
final matrix = Matrix4.identity()
|
||||||
..translate(value.position.dx, value.position.dy)
|
..translateByDouble(value.position.dx, value.position.dy, 0, 1.0)
|
||||||
..scale(computedScale)
|
..scaleByDouble(computedScale, computedScale, computedScale, 1.0)
|
||||||
..rotateZ(value.rotation);
|
..rotateZ(value.rotation);
|
||||||
|
|
||||||
final Widget customChildLayout = CustomSingleChildLayout(
|
final Widget customChildLayout = CustomSingleChildLayout(
|
||||||
|
|||||||
@ -13,40 +13,19 @@ class MediaTypePicker extends HookWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final selectedMediaType = useState(filter ?? AssetType.other);
|
final selectedMediaType = useState(filter ?? AssetType.other);
|
||||||
|
|
||||||
return ListView(
|
return RadioGroup(
|
||||||
shrinkWrap: true,
|
onChanged: (value) {
|
||||||
children: [
|
selectedMediaType.value = value!;
|
||||||
RadioListTile(
|
onSelect(value);
|
||||||
key: const Key("all"),
|
},
|
||||||
title: const Text("all").tr(),
|
groupValue: selectedMediaType.value,
|
||||||
value: AssetType.other,
|
child: Column(
|
||||||
onChanged: (value) {
|
children: [
|
||||||
selectedMediaType.value = value!;
|
RadioListTile(key: const Key("all"), title: const Text("all").tr(), value: AssetType.other),
|
||||||
onSelect(value);
|
RadioListTile(key: const Key("image"), title: const Text("image").tr(), value: AssetType.image),
|
||||||
},
|
RadioListTile(key: const Key("video"), title: const Text("video").tr(), value: AssetType.video),
|
||||||
groupValue: selectedMediaType.value,
|
],
|
||||||
),
|
),
|
||||||
RadioListTile(
|
|
||||||
key: const Key("image"),
|
|
||||||
title: const Text("image").tr(),
|
|
||||||
value: AssetType.image,
|
|
||||||
onChanged: (value) {
|
|
||||||
selectedMediaType.value = value!;
|
|
||||||
onSelect(value);
|
|
||||||
},
|
|
||||||
groupValue: selectedMediaType.value,
|
|
||||||
),
|
|
||||||
RadioListTile(
|
|
||||||
key: const Key("video"),
|
|
||||||
title: const Text("video").tr(),
|
|
||||||
value: AssetType.video,
|
|
||||||
onChanged: (value) {
|
|
||||||
selectedMediaType.value = value!;
|
|
||||||
onSelect(value);
|
|
||||||
},
|
|
||||||
groupValue: selectedMediaType.value,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,7 +62,7 @@ class BetaTimelineListTile extends ConsumerWidget {
|
|||||||
trailing: Switch.adaptive(
|
trailing: Switch.adaptive(
|
||||||
value: betaTimelineValue,
|
value: betaTimelineValue,
|
||||||
onChanged: onSwitchChanged,
|
onChanged: onSwitchChanged,
|
||||||
activeColor: context.primaryColor,
|
activeThumbColor: context.primaryColor,
|
||||||
),
|
),
|
||||||
onTap: () => onSwitchChanged(!betaTimelineValue),
|
onTap: () => onSwitchChanged(!betaTimelineValue),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -115,7 +115,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
|||||||
child: SwitchListTile.adaptive(
|
child: SwitchListTile.adaptive(
|
||||||
contentPadding: const EdgeInsets.symmetric(vertical: 6, horizontal: 20),
|
contentPadding: const EdgeInsets.symmetric(vertical: 6, horizontal: 20),
|
||||||
dense: true,
|
dense: true,
|
||||||
activeColor: context.primaryColor,
|
activeThumbColor: context.primaryColor,
|
||||||
tileColor: context.colorScheme.surfaceContainerHigh,
|
tileColor: context.colorScheme.surfaceContainerHigh,
|
||||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15))),
|
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15))),
|
||||||
title: Text(
|
title: Text(
|
||||||
|
|||||||
@ -9,7 +9,7 @@ class SettingsRadioGroup<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SettingsRadioListTile<T> extends StatelessWidget {
|
class SettingsRadioListTile<T> extends StatelessWidget {
|
||||||
final List<SettingsRadioGroup> groups;
|
final List<SettingsRadioGroup<T>> groups;
|
||||||
final T groupBy;
|
final T groupBy;
|
||||||
final void Function(T?) onRadioChanged;
|
final void Function(T?) onRadioChanged;
|
||||||
|
|
||||||
@ -17,21 +17,23 @@ class SettingsRadioListTile<T> extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return RadioGroup(
|
||||||
children: groups
|
groupValue: groupBy,
|
||||||
.map(
|
onChanged: onRadioChanged,
|
||||||
(g) => RadioListTile<T>(
|
child: Column(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 20),
|
children: groups
|
||||||
dense: true,
|
.map(
|
||||||
activeColor: context.primaryColor,
|
(g) => RadioListTile<T>(
|
||||||
title: Text(g.title, style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500)),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
value: g.value,
|
dense: true,
|
||||||
groupValue: groupBy,
|
activeColor: context.primaryColor,
|
||||||
onChanged: onRadioChanged,
|
title: Text(g.title, style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500)),
|
||||||
controlAffinity: ListTileControlAffinity.trailing,
|
value: g.value,
|
||||||
),
|
controlAffinity: ListTileControlAffinity.trailing,
|
||||||
)
|
),
|
||||||
.toList(),
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ class SettingsSwitchListTile extends StatelessWidget {
|
|||||||
selectedTileColor: enabled ? null : context.themeData.disabledColor,
|
selectedTileColor: enabled ? null : context.themeData.disabledColor,
|
||||||
value: valueNotifier.value,
|
value: valueNotifier.value,
|
||||||
onChanged: onSwitchChanged,
|
onChanged: onSwitchChanged,
|
||||||
activeColor: enabled ? context.primaryColor : context.themeData.disabledColor,
|
activeThumbColor: enabled ? context.primaryColor : context.themeData.disabledColor,
|
||||||
dense: true,
|
dense: true,
|
||||||
secondary: icon != null ? Icon(icon!, color: valueNotifier.value ? context.primaryColor : null) : null,
|
secondary: icon != null ? Icon(icon!, color: valueNotifier.value ? context.primaryColor : null) : null,
|
||||||
title: Text(
|
title: Text(
|
||||||
|
|||||||
@ -1064,26 +1064,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.9"
|
version: "11.0.2"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.9"
|
version: "3.0.10"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_testing
|
name: leak_tracker_testing
|
||||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1877,10 +1877,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.4"
|
version: "0.7.6"
|
||||||
thumbhash:
|
thumbhash:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -2037,10 +2037,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.2.0"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -2171,4 +2171,4 @@ packages:
|
|||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.8.0 <4.0.0"
|
dart: ">=3.8.0 <4.0.0"
|
||||||
flutter: ">=3.32.8"
|
flutter: ">=3.35.3"
|
||||||
|
|||||||
@ -6,7 +6,7 @@ version: 1.142.1+3015
|
|||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.8.0 <4.0.0'
|
sdk: '>=3.8.0 <4.0.0'
|
||||||
flutter: 3.32.8
|
flutter: 3.35.3
|
||||||
|
|
||||||
isar_version: &isar_version 3.1.8
|
isar_version: &isar_version 3.1.8
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ RUN if [ "$(dpkg --print-architecture)" = "arm64" ]; then \
|
|||||||
# Flutter SDK
|
# Flutter SDK
|
||||||
# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux
|
# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux
|
||||||
ENV FLUTTER_CHANNEL="stable"
|
ENV FLUTTER_CHANNEL="stable"
|
||||||
ENV FLUTTER_VERSION="3.32.8"
|
ENV FLUTTER_VERSION="3.35.3"
|
||||||
ENV FLUTTER_HOME=/flutter
|
ENV FLUTTER_HOME=/flutter
|
||||||
ENV PATH=${PATH}:${FLUTTER_HOME}/bin
|
ENV PATH=${PATH}:${FLUTTER_HOME}/bin
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
"build:stats": "BUILD_STATS=true vite build",
|
"build:stats": "BUILD_STATS=true vite build",
|
||||||
"package": "svelte-kit package",
|
"package": "svelte-kit package",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"check:svelte": "svelte-check --no-tsconfig --fail-on-warnings --compiler-warnings 'reactive_declaration_non_reactive_property:ignore' --ignore src/lib/components/timeline/Timeline.svelte",
|
"check:svelte": "svelte-check --no-tsconfig --fail-on-warnings",
|
||||||
"check:typescript": "tsc --noEmit",
|
"check:typescript": "tsc --noEmit",
|
||||||
"check:watch": "npm run check:svelte -- --watch",
|
"check:watch": "npm run check:svelte -- --watch",
|
||||||
"check:code": "npm run format && npm run lint:p && npm run check:svelte && npm run check:typescript",
|
"check:code": "npm run format && npm run lint:p && npm run check:svelte && npm run check:typescript",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user