mirror of
https://github.com/immich-app/immich.git
synced 2024-12-26 10:50:29 +02:00
feat(mobile): improved logging page experience (#2158)
* feat(mobile): improve logging page * Use new API for share file * removed unused code * Better safe area on the home screen * Added preparing share dialog to home screen
This commit is contained in:
parent
2dcccb37a0
commit
d6f2ca6aaa
@ -27,6 +27,7 @@ import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
|||||||
import 'package:immich_mobile/shared/services/share.service.dart';
|
import 'package:immich_mobile/shared/services/share.service.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||||
|
import 'package:immich_mobile/shared/ui/share_dialog.dart';
|
||||||
|
|
||||||
class HomePage extends HookConsumerWidget {
|
class HomePage extends HookConsumerWidget {
|
||||||
const HomePage({Key? key}) : super(key: key);
|
const HomePage({Key? key}) : super(key: key);
|
||||||
@ -81,7 +82,19 @@ class HomePage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onShareAssets() {
|
void onShareAssets() {
|
||||||
ref.watch(shareServiceProvider).shareAssets(selection.value.toList());
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext buildContext) {
|
||||||
|
ref
|
||||||
|
.watch(shareServiceProvider)
|
||||||
|
.shareAssets(selection.value.toList())
|
||||||
|
.then((_) => Navigator.of(buildContext).pop());
|
||||||
|
return const ShareDialog();
|
||||||
|
},
|
||||||
|
barrierDismissible: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ref.watch(shareServiceProvider).shareAssets(selection.value.toList());
|
||||||
selectionEnabledHook.value = false;
|
selectionEnabledHook.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +257,7 @@ class HomePage extends HookConsumerWidget {
|
|||||||
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
top: true,
|
top: true,
|
||||||
|
bottom: false,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
ref.watch(assetProvider).renderList == null ||
|
ref.watch(assetProvider).renderList == null ||
|
||||||
@ -261,17 +275,14 @@ class HomePage extends HookConsumerWidget {
|
|||||||
onRefresh: refreshAssets,
|
onRefresh: refreshAssets,
|
||||||
),
|
),
|
||||||
if (selectionEnabledHook.value)
|
if (selectionEnabledHook.value)
|
||||||
SafeArea(
|
ControlBottomAppBar(
|
||||||
bottom: true,
|
onShare: onShareAssets,
|
||||||
child: ControlBottomAppBar(
|
onFavorite: onFavoriteAssets,
|
||||||
onShare: onShareAssets,
|
onDelete: onDelete,
|
||||||
onFavorite: onFavoriteAssets,
|
onAddToAlbum: onAddToAlbum,
|
||||||
onDelete: onDelete,
|
albums: albums,
|
||||||
onAddToAlbum: onAddToAlbum,
|
sharedAlbums: sharedAlbums,
|
||||||
albums: albums,
|
onCreateNewAlbum: onCreateNewAlbum,
|
||||||
sharedAlbums: sharedAlbums,
|
|
||||||
onCreateNewAlbum: onCreateNewAlbum,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -279,9 +290,11 @@ class HomePage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: HomePageAppBar(
|
appBar: !selectionEnabledHook.value
|
||||||
onPopBack: reloadAllAsset,
|
? HomePageAppBar(
|
||||||
),
|
onPopBack: reloadAllAsset,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
drawer: const ProfileDrawer(),
|
drawer: const ProfileDrawer(),
|
||||||
body: buildBody(),
|
body: buildBody(),
|
||||||
);
|
);
|
||||||
|
@ -34,8 +34,10 @@ import 'package:immich_mobile/routing/duplicate_guard.dart';
|
|||||||
import 'package:immich_mobile/routing/gallery_permission_guard.dart';
|
import 'package:immich_mobile/routing/gallery_permission_guard.dart';
|
||||||
import 'package:immich_mobile/shared/models/asset.dart';
|
import 'package:immich_mobile/shared/models/asset.dart';
|
||||||
import 'package:immich_mobile/shared/models/album.dart';
|
import 'package:immich_mobile/shared/models/album.dart';
|
||||||
|
import 'package:immich_mobile/shared/models/logger_message.model.dart';
|
||||||
import 'package:immich_mobile/shared/providers/api.provider.dart';
|
import 'package:immich_mobile/shared/providers/api.provider.dart';
|
||||||
import 'package:immich_mobile/shared/services/api.service.dart';
|
import 'package:immich_mobile/shared/services/api.service.dart';
|
||||||
|
import 'package:immich_mobile/shared/views/app_log_detail_page.dart';
|
||||||
import 'package:immich_mobile/shared/views/app_log_page.dart';
|
import 'package:immich_mobile/shared/views/app_log_page.dart';
|
||||||
import 'package:immich_mobile/shared/views/splash_screen.dart';
|
import 'package:immich_mobile/shared/views/splash_screen.dart';
|
||||||
import 'package:immich_mobile/shared/views/tab_controller_page.dart';
|
import 'package:immich_mobile/shared/views/tab_controller_page.dart';
|
||||||
@ -47,8 +49,12 @@ part 'router.gr.dart';
|
|||||||
replaceInRouteName: 'Page,Route',
|
replaceInRouteName: 'Page,Route',
|
||||||
routes: <AutoRoute>[
|
routes: <AutoRoute>[
|
||||||
AutoRoute(page: SplashScreenPage, initial: true),
|
AutoRoute(page: SplashScreenPage, initial: true),
|
||||||
AutoRoute(page: PermissionOnboardingPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(
|
||||||
AutoRoute(page: LoginPage,
|
page: PermissionOnboardingPage,
|
||||||
|
guards: [AuthGuard, DuplicateGuard],
|
||||||
|
),
|
||||||
|
AutoRoute(
|
||||||
|
page: LoginPage,
|
||||||
guards: [
|
guards: [
|
||||||
DuplicateGuard,
|
DuplicateGuard,
|
||||||
],
|
],
|
||||||
@ -65,7 +71,10 @@ part 'router.gr.dart';
|
|||||||
],
|
],
|
||||||
transitionsBuilder: TransitionsBuilders.fadeIn,
|
transitionsBuilder: TransitionsBuilders.fadeIn,
|
||||||
),
|
),
|
||||||
AutoRoute(page: GalleryViewerPage, guards: [AuthGuard, DuplicateGuard, GalleryPermissionGuard]),
|
AutoRoute(
|
||||||
|
page: GalleryViewerPage,
|
||||||
|
guards: [AuthGuard, DuplicateGuard, GalleryPermissionGuard],
|
||||||
|
),
|
||||||
AutoRoute(page: VideoViewerPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(page: VideoViewerPage, guards: [AuthGuard, DuplicateGuard]),
|
||||||
AutoRoute(page: BackupControllerPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(page: BackupControllerPage, guards: [AuthGuard, DuplicateGuard]),
|
||||||
AutoRoute(page: SearchResultPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(page: SearchResultPage, guards: [AuthGuard, DuplicateGuard]),
|
||||||
@ -75,7 +84,10 @@ part 'router.gr.dart';
|
|||||||
AutoRoute(page: FavoritesPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(page: FavoritesPage, guards: [AuthGuard, DuplicateGuard]),
|
||||||
AutoRoute(page: AllVideosPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(page: AllVideosPage, guards: [AuthGuard, DuplicateGuard]),
|
||||||
AutoRoute(page: AllMotionPhotosPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(page: AllMotionPhotosPage, guards: [AuthGuard, DuplicateGuard]),
|
||||||
AutoRoute(page: RecentlyAddedPage, guards: [AuthGuard, DuplicateGuard],),
|
AutoRoute(
|
||||||
|
page: RecentlyAddedPage,
|
||||||
|
guards: [AuthGuard, DuplicateGuard],
|
||||||
|
),
|
||||||
CustomRoute<AssetSelectionPageResult?>(
|
CustomRoute<AssetSelectionPageResult?>(
|
||||||
page: AssetSelectionPage,
|
page: AssetSelectionPage,
|
||||||
guards: [AuthGuard, DuplicateGuard],
|
guards: [AuthGuard, DuplicateGuard],
|
||||||
@ -92,14 +104,18 @@ part 'router.gr.dart';
|
|||||||
guards: [AuthGuard, DuplicateGuard],
|
guards: [AuthGuard, DuplicateGuard],
|
||||||
transitionsBuilder: TransitionsBuilders.slideBottom,
|
transitionsBuilder: TransitionsBuilders.slideBottom,
|
||||||
),
|
),
|
||||||
AutoRoute(page: BackupAlbumSelectionPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(
|
||||||
|
page: BackupAlbumSelectionPage,
|
||||||
|
guards: [AuthGuard, DuplicateGuard],
|
||||||
|
),
|
||||||
AutoRoute(page: AlbumPreviewPage, guards: [AuthGuard, DuplicateGuard]),
|
AutoRoute(page: AlbumPreviewPage, guards: [AuthGuard, DuplicateGuard]),
|
||||||
CustomRoute(
|
CustomRoute(
|
||||||
page: FailedBackupStatusPage,
|
page: FailedBackupStatusPage,
|
||||||
guards: [AuthGuard, DuplicateGuard],
|
guards: [AuthGuard, DuplicateGuard],
|
||||||
transitionsBuilder: TransitionsBuilders.slideBottom,
|
transitionsBuilder: TransitionsBuilders.slideBottom,
|
||||||
),
|
),
|
||||||
AutoRoute(page: SettingsPage,
|
AutoRoute(
|
||||||
|
page: SettingsPage,
|
||||||
guards: [
|
guards: [
|
||||||
AuthGuard,
|
AuthGuard,
|
||||||
DuplicateGuard,
|
DuplicateGuard,
|
||||||
@ -109,6 +125,9 @@ part 'router.gr.dart';
|
|||||||
page: AppLogPage,
|
page: AppLogPage,
|
||||||
transitionsBuilder: TransitionsBuilders.slideBottom,
|
transitionsBuilder: TransitionsBuilders.slideBottom,
|
||||||
),
|
),
|
||||||
|
AutoRoute(
|
||||||
|
page: AppLogDetailPage,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
class AppRouter extends _$AppRouter {
|
class AppRouter extends _$AppRouter {
|
||||||
@ -118,12 +137,17 @@ class AppRouter extends _$AppRouter {
|
|||||||
AppRouter(
|
AppRouter(
|
||||||
this._apiService,
|
this._apiService,
|
||||||
GalleryPermissionNotifier galleryPermissionNotifier,
|
GalleryPermissionNotifier galleryPermissionNotifier,
|
||||||
) : super(
|
) : super(
|
||||||
authGuard: AuthGuard(_apiService),
|
authGuard: AuthGuard(_apiService),
|
||||||
duplicateGuard: DuplicateGuard(),
|
duplicateGuard: DuplicateGuard(),
|
||||||
galleryPermissionGuard: GalleryPermissionGuard(galleryPermissionNotifier),
|
galleryPermissionGuard:
|
||||||
|
GalleryPermissionGuard(galleryPermissionNotifier),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final appRouterProvider =
|
final appRouterProvider = Provider(
|
||||||
Provider((ref) => AppRouter(ref.watch(apiServiceProvider), ref.watch(galleryPermissionNotifier.notifier)));
|
(ref) => AppRouter(
|
||||||
|
ref.watch(apiServiceProvider),
|
||||||
|
ref.watch(galleryPermissionNotifier.notifier),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
@ -230,6 +230,16 @@ class _$AppRouter extends RootStackRouter {
|
|||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
AppLogDetailRoute.name: (routeData) {
|
||||||
|
final args = routeData.argsAs<AppLogDetailRouteArgs>();
|
||||||
|
return MaterialPageX<dynamic>(
|
||||||
|
routeData: routeData,
|
||||||
|
child: AppLogDetailPage(
|
||||||
|
key: args.key,
|
||||||
|
logMessage: args.logMessage,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
HomeRoute.name: (routeData) {
|
HomeRoute.name: (routeData) {
|
||||||
return MaterialPageX<dynamic>(
|
return MaterialPageX<dynamic>(
|
||||||
routeData: routeData,
|
routeData: routeData,
|
||||||
@ -485,6 +495,10 @@ class _$AppRouter extends RootStackRouter {
|
|||||||
AppLogRoute.name,
|
AppLogRoute.name,
|
||||||
path: '/app-log-page',
|
path: '/app-log-page',
|
||||||
),
|
),
|
||||||
|
RouteConfig(
|
||||||
|
AppLogDetailRoute.name,
|
||||||
|
path: '/app-log-detail-page',
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -974,6 +988,40 @@ class AppLogRoute extends PageRouteInfo<void> {
|
|||||||
static const String name = 'AppLogRoute';
|
static const String name = 'AppLogRoute';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// generated route for
|
||||||
|
/// [AppLogDetailPage]
|
||||||
|
class AppLogDetailRoute extends PageRouteInfo<AppLogDetailRouteArgs> {
|
||||||
|
AppLogDetailRoute({
|
||||||
|
Key? key,
|
||||||
|
required LoggerMessage logMessage,
|
||||||
|
}) : super(
|
||||||
|
AppLogDetailRoute.name,
|
||||||
|
path: '/app-log-detail-page',
|
||||||
|
args: AppLogDetailRouteArgs(
|
||||||
|
key: key,
|
||||||
|
logMessage: logMessage,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
static const String name = 'AppLogDetailRoute';
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppLogDetailRouteArgs {
|
||||||
|
const AppLogDetailRouteArgs({
|
||||||
|
this.key,
|
||||||
|
required this.logMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Key? key;
|
||||||
|
|
||||||
|
final LoggerMessage logMessage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AppLogDetailRouteArgs{key: $key, logMessage: $logMessage}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [HomePage]
|
/// [HomePage]
|
||||||
class HomeRoute extends PageRouteInfo<void> {
|
class HomeRoute extends PageRouteInfo<void> {
|
||||||
|
@ -102,15 +102,13 @@ class ImmichLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Share file
|
// Share file
|
||||||
// ignore: deprecated_member_use
|
await Share.shareXFiles(
|
||||||
await Share.shareFiles(
|
[XFile(filePath)],
|
||||||
[filePath],
|
|
||||||
subject: "Immich logs $dateTime",
|
subject: "Immich logs $dateTime",
|
||||||
sharePositionOrigin: Rect.zero,
|
sharePositionOrigin: Rect.zero,
|
||||||
|
).then(
|
||||||
|
(value) => logFile.delete(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Clean up temp file
|
|
||||||
await logFile.delete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flush pending log messages to persistent storage
|
/// Flush pending log messages to persistent storage
|
||||||
|
@ -36,7 +36,6 @@ class ShareService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ignore: deprecated_member_use
|
|
||||||
Share.shareXFiles(
|
Share.shareXFiles(
|
||||||
await Future.wait(downloadedXFiles),
|
await Future.wait(downloadedXFiles),
|
||||||
sharePositionOrigin: Rect.zero,
|
sharePositionOrigin: Rect.zero,
|
||||||
|
@ -369,7 +369,6 @@ class SyncService {
|
|||||||
List<AssetPathEntity> onDevice, [
|
List<AssetPathEntity> onDevice, [
|
||||||
Set<String>? excludedAssets,
|
Set<String>? excludedAssets,
|
||||||
]) async {
|
]) async {
|
||||||
_log.info("Syncing ${onDevice.length} albums from device: $onDevice");
|
|
||||||
onDevice.sort((a, b) => a.id.compareTo(b.id));
|
onDevice.sort((a, b) => a.id.compareTo(b.id));
|
||||||
final List<Album> inDb =
|
final List<Album> inDb =
|
||||||
await _db.albums.where().localIdIsNotNull().sortByLocalId().findAll();
|
await _db.albums.where().localIdIsNotNull().sortByLocalId().findAll();
|
||||||
|
190
mobile/lib/shared/views/app_log_detail_page.dart
Normal file
190
mobile/lib/shared/views/app_log_detail_page.dart
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/shared/models/logger_message.model.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
class AppLogDetailPage extends HookConsumerWidget {
|
||||||
|
const AppLogDetailPage({super.key, required this.logMessage});
|
||||||
|
|
||||||
|
final LoggerMessage logMessage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
var isDarkMode = Theme.of(context).brightness == Brightness.dark;
|
||||||
|
|
||||||
|
buildStackMessage(String stackTrace) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"STACK TRACES",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12.0,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: stackTrace))
|
||||||
|
.then((_) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text("Copied to clipboard")),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.copy,
|
||||||
|
size: 16.0,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isDarkMode ? Colors.grey[900] : Colors.grey[200],
|
||||||
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: SelectableText(
|
||||||
|
stackTrace,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 12.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontFamily: "Inconsolata",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildLogMessage(String message) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"MESSAGE",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12.0,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: message)).then((_) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text("Copied to clipboard")),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.copy,
|
||||||
|
size: 16.0,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isDarkMode ? Colors.grey[900] : Colors.grey[200],
|
||||||
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: SelectableText(
|
||||||
|
message,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 12.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontFamily: "Inconsolata",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildLogContext1(String context1) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"FROM",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12.0,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isDarkMode ? Colors.grey[900] : Colors.grey[200],
|
||||||
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: SelectableText(
|
||||||
|
context1.toString(),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 12.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontFamily: "Inconsolata",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Log Detail"),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
buildLogMessage(logMessage.message),
|
||||||
|
if (logMessage.context1 != null)
|
||||||
|
buildLogContext1(logMessage.context1.toString()),
|
||||||
|
if (logMessage.context2 != null)
|
||||||
|
buildStackMessage(logMessage.context2.toString())
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/shared/models/logger_message.model.dart';
|
import 'package:immich_mobile/shared/models/logger_message.model.dart';
|
||||||
import 'package:immich_mobile/shared/services/immich_logger.service.dart';
|
import 'package:immich_mobile/shared/services/immich_logger.service.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@ -123,6 +124,12 @@ class AppLogPage extends HookConsumerWidget {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
var logMessage = logMessages.value[index];
|
var logMessage = logMessages.value[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
|
onTap: () => AutoRouter.of(context).push(
|
||||||
|
AppLogDetailRoute(
|
||||||
|
logMessage: logMessage,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: const Icon(Icons.arrow_forward_ios_rounded),
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
dense: true,
|
dense: true,
|
||||||
tileColor: getTileColor(logMessage.level),
|
tileColor: getTileColor(logMessage.level),
|
||||||
|
Loading…
Reference in New Issue
Block a user