Skip to content
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
103 changes: 103 additions & 0 deletions example/lib/utils/ensure_resource.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/// Utility to ensure a Pod resource exists before performing actions on it.
///
/// Copyright (C) 2026, Software Innovation Institute, ANU.
///
/// Licensed under the GNU General Public License, Version 3 (the "License").
///
/// License: https://opensource.org/license/gpl-3-0.
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <https://opensource.org/license/gpl-3-0>.
///
/// Authors: Tony Chen

// ignore_for_file: use_build_context_synchronously

library;

import 'package:flutter/material.dart';

import 'package:solidpod/solidpod.dart'
show ResourceStatus, checkResourceStatus, filenameToResourceUrl, writePod;

import 'package:demopod/dialogs/alert.dart';

/// Ensures the resource at [relativePath] exists in the user's Pod.
///
/// The [relativePath] is interpreted relative to the app's data directory
/// (e.g. `keyvalue/key-value.ttl`). When the resource is missing on the Pod,
/// a new file is created using [defaultContent] (encrypted by default) so
/// downstream actions such as granting permissions do not fail.
///
/// Returns `true` when the resource is available (already existed or was
/// just created), and `false` otherwise.

Future<bool> ensurePodResourceExists(
BuildContext context, {
required String relativePath,
required String defaultContent,
bool encrypted = true,
}) async {
try {
final fileUrl = await filenameToResourceUrl(fileName: relativePath);

final status = await checkResourceStatus(fileUrl);

switch (status) {
case ResourceStatus.exist:
return true;

case ResourceStatus.notExist:
await writePod(relativePath, defaultContent, encrypted: encrypted);

if (context.mounted) {
await alert(
context,
'The resource "$relativePath" did not exist on your Pod, '
'so a new file with placeholder content has been created '
'automatically.',
);
}
return true;

case ResourceStatus.forbidden:
if (context.mounted) {
await alert(
context,
'Access to "$relativePath" is forbidden. Please check the '
'permissions on your Pod and try again.',
);
}
return false;

case ResourceStatus.unknown:
if (context.mounted) {
await alert(
context,
'Unable to determine whether "$relativePath" exists on your Pod. '
'Please try again in a moment.',
);
}
return false;
}
} on Object catch (e) {
debugPrint('ensurePodResourceExists() failed: $e');
if (context.mounted) {
await alert(
context,
'Failed to ensure "$relativePath" exists on your Pod: $e',
);
}
return false;
}
}
29 changes: 28 additions & 1 deletion example/lib/widgets/home_sections.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import 'package:solidui/solidui.dart'
import 'package:demopod/constants/app.dart';
import 'package:demopod/features/permission_callback_demo.dart';
import 'package:demopod/features/multiple_resource_sharing.dart';
import 'package:demopod/utils/ensure_resource.dart';

/// Builds the login management section widgets.

Expand Down Expand Up @@ -148,12 +149,25 @@ List<Widget> buildPermissionSection(
if (loggedIn) {
await getKeyFromUserIfRequired(context, currentWidget);

// Ensure the target resource exists on the Pod before opening the
// grant permission UI. The button previously failed with a "not
// found" error when keyvalue/key-value.ttl had never been created.

if (!context.mounted) return;
final ready = await ensurePodResourceExists(
context,
relativePath: dataFile,
defaultContent: createDemoTtlStr('key-value'),
);
if (!ready) return;

if (!context.mounted) return;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GrantPermissionUi(
backgroundColor: titleBackgroundColor,
resourceNames: ['keyvalue/key-value.ttl'],
resourceNames: [dataFile],
// accessModeList: ['read', 'write'],
// recipientTypeList: ['indi', 'group'],
// isFile: false,
Expand Down Expand Up @@ -253,6 +267,19 @@ List<Widget> buildPermissionSection(
if (loggedIn) {
await getKeyFromUserIfRequired(context, currentWidget);

// Ensure the target resource exists on the Pod before opening the
// shared resources UI. The button previously failed with a "not
// found" error when keyvalue/key-value.ttl had never been created.

if (!context.mounted) return;
final ready = await ensurePodResourceExists(
context,
relativePath: dataFile,
defaultContent: createDemoTtlStr('key-value'),
);
if (!ready) return;

if (!context.mounted) return;
Navigator.push(
context,
MaterialPageRoute(
Expand Down
4 changes: 2 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ dependencies:
intl: any
markdown_tooltip: ^0.0.10
rdflib: ^0.2.12
solidpod: ^0.12.5
solidui: ^0.3.43
solidpod: ^0.12.6
solidui: ^0.3.45
universal_io: ^2.3.1
window_manager: ^0.5.1

Expand Down
Loading