mirror of
https://github.com/chenasraf/pantry-flutter.git
synced 2026-05-17 17:28:03 +00:00
feat: handle server app not installed
This commit is contained in:
@@ -175,6 +175,27 @@ class HomeMessages {
|
||||
/// "Failed to load houses."
|
||||
/// ```
|
||||
String get failedToLoadHouses => """Failed to load houses.""";
|
||||
|
||||
/// ```dart
|
||||
/// "Pantry is not installed"
|
||||
/// ```
|
||||
String get serverAppMissingTitle => """Pantry is not installed""";
|
||||
|
||||
/// ```dart
|
||||
/// "This app is a client for the Pantry app on Nextcloud. It looks like Pantry isn't installed on your server yet. Ask your administrator to install it from the Nextcloud app store, or install it yourself if you have admin access."
|
||||
/// ```
|
||||
String get serverAppMissingBody =>
|
||||
"""This app is a client for the Pantry app on Nextcloud. It looks like Pantry isn't installed on your server yet. Ask your administrator to install it from the Nextcloud app store, or install it yourself if you have admin access.""";
|
||||
|
||||
/// ```dart
|
||||
/// "Open Nextcloud apps"
|
||||
/// ```
|
||||
String get openAppStore => """Open Nextcloud apps""";
|
||||
|
||||
/// ```dart
|
||||
/// "Learn more"
|
||||
/// ```
|
||||
String get learnMore => """Learn more""";
|
||||
}
|
||||
|
||||
class NavMessages {
|
||||
@@ -860,6 +881,11 @@ Please complete login in your browser.""",
|
||||
"""login.loginFailed""": """Login failed. Please try again.""",
|
||||
"""home.noHouses""": """No houses found. Create one in Nextcloud first.""",
|
||||
"""home.failedToLoadHouses""": """Failed to load houses.""",
|
||||
"""home.serverAppMissingTitle""": """Pantry is not installed""",
|
||||
"""home.serverAppMissingBody""":
|
||||
"""This app is a client for the Pantry app on Nextcloud. It looks like Pantry isn't installed on your server yet. Ask your administrator to install it from the Nextcloud app store, or install it yourself if you have admin access.""",
|
||||
"""home.openAppStore""": """Open Nextcloud apps""",
|
||||
"""home.learnMore""": """Learn more""",
|
||||
"""nav.checklists""": """Checklists""",
|
||||
"""nav.photoBoard""": """Photo Board""",
|
||||
"""nav.notesWall""": """Notes Wall""",
|
||||
|
||||
@@ -20,6 +20,10 @@ login:
|
||||
home:
|
||||
noHouses: No houses found. Create one in Nextcloud first.
|
||||
failedToLoadHouses: Failed to load houses.
|
||||
serverAppMissingTitle: Pantry is not installed
|
||||
serverAppMissingBody: "This app is a client for the Pantry app on Nextcloud. It looks like Pantry isn't installed on your server yet. Ask your administrator to install it from the Nextcloud app store, or install it yourself if you have admin access."
|
||||
openAppStore: Open Nextcloud apps
|
||||
learnMore: Learn more
|
||||
|
||||
nav:
|
||||
checklists: Checklists
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:pantry/i18n.dart';
|
||||
import 'package:pantry/models/house.dart';
|
||||
import 'package:pantry/services/api_client.dart';
|
||||
import 'package:pantry/services/house_service.dart';
|
||||
import 'package:pantry/services/prefs_service.dart';
|
||||
|
||||
@@ -17,8 +18,14 @@ class HomeController extends ChangeNotifier {
|
||||
String? _error;
|
||||
String? get error => _error;
|
||||
|
||||
/// True when the Pantry server app is not installed on the user's
|
||||
/// Nextcloud instance (API returns 404).
|
||||
bool _serverAppMissing = false;
|
||||
bool get serverAppMissing => _serverAppMissing;
|
||||
|
||||
Future<void> load() async {
|
||||
_error = null;
|
||||
_serverAppMissing = false;
|
||||
|
||||
// Restore from cache
|
||||
final cached = HouseService.instance.getCached();
|
||||
@@ -52,7 +59,11 @@ class HomeController extends ChangeNotifier {
|
||||
} catch (e) {
|
||||
debugPrint('[HomeController] Failed to load houses: $e');
|
||||
if (_houses.isEmpty) {
|
||||
_error = m.home.failedToLoadHouses;
|
||||
if (e is ApiException && e.statusCode == 404) {
|
||||
_serverAppMissing = true;
|
||||
} else {
|
||||
_error = m.home.failedToLoadHouses;
|
||||
}
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import 'package:pantry/i18n.dart';
|
||||
import 'package:pantry/models/house.dart';
|
||||
@@ -105,6 +106,10 @@ class _HomeViewBodyState extends State<_HomeViewBody> {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (controller.serverAppMissing) {
|
||||
return _ServerAppMissingView(onRetry: controller.load);
|
||||
}
|
||||
|
||||
if (controller.error != null) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
@@ -241,3 +246,70 @@ class _UserMenuButton extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ServerAppMissingView extends StatelessWidget {
|
||||
final VoidCallback onRetry;
|
||||
|
||||
const _ServerAppMissingView({required this.onRetry});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final serverUrl = AuthService.instance.credentials?.serverUrl ?? '';
|
||||
// Nextcloud app store path for pantry
|
||||
final appUrl = '$serverUrl/settings/apps/organization/pantry';
|
||||
final infoUrl = 'https://apps.nextcloud.com/apps/pantry';
|
||||
|
||||
return Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.extension_off_outlined,
|
||||
size: 72,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
m.home.serverAppMissingTitle,
|
||||
style: theme.textTheme.headlineSmall,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
m.home.serverAppMissingBody,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
FilledButton.icon(
|
||||
onPressed: () => _launch(appUrl),
|
||||
icon: const Icon(Icons.open_in_new),
|
||||
label: Text(m.home.openAppStore),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextButton.icon(
|
||||
onPressed: () => _launch(infoUrl),
|
||||
icon: const Icon(Icons.info_outline),
|
||||
label: Text(m.home.learnMore),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextButton(onPressed: onRetry, child: Text(m.common.retry)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _launch(String url) async {
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user