Skip to content
Open
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
131 changes: 126 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ utilising the solidui package.
- [Requirements](#requirements)
- [SolidScaffold](#solidscaffold)
- [SolidFile](#solidfile)
- [Grant Permission UI Example](#grant-permission-ui-example)
- [View Permission UI Example](#view-permission-ui-example)
- [Authentication and Login Detection](#authentication-and-login-detection)
- [Security Key Management](#security-key-management)
- [API Reference](#api-reference)
Expand Down Expand Up @@ -115,23 +117,22 @@ Fine tune to suit the theme of the app:
- For defining specific access mode types or recipient types, use
optional parameters `accessModeList` and `recipientTypeList`.

Granting permission (currently ublished in solidpod):
Granting permission:
<div align="center">
<img
src="https://raw.githubusercontent.com/anusii/solidui/main/assets/screenshots/grant_permission.png"
alt="KeyPod Login" width="400">
alt="Grant Permission" width="400">
</div>

Revoking permission:
<div align="center">
<img
src="https://raw.githubusercontent.com/anusii/solidui/main/assets/screenshots/revoke_permission.png"
alt="KeyPod Login" width="400">
alt="Revoke Permission" width="400">
</div>

- SharedResourcesUi widget displays
resources shared with a Pod by others (currently published in
solidpod):
resources shared with a Pod by others:

<div align="center">
<img
Expand Down Expand Up @@ -780,6 +781,126 @@ ElevatedButton(
)
```

## Grant Permission UI Example

The `GrantPermissionUi` widget provides a full-featured page for
granting, editing, and revoking access permissions on resources stored
in a Solid POD. Wrap it inside a navigation action to reach the
permission management page.

### Basic usage (browse all resources)

```dart
ElevatedButton(
child: const Text('Add/Delete Permissions'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const GrantPermissionUi(
child: ReturnPage(),
),
),
),
)
```

### Permissions for a specific file

```dart
ElevatedButton(
child: const Text('Add/Delete Permissions from a Specific File'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const GrantPermissionUi(
resourceName: 'my-data-file.ttl',
child: ReturnPage(),
),
),
),
)
```

### Permissions for a specific directory

```dart
ElevatedButton(
child: const Text('Add/Delete Permissions from a Specific Directory'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const GrantPermissionUi(
resourceName: 'parentDir/',
child: ReturnPage(),
isFile: false,
),
),
),
)
```

### Permissions for an externally owned resource

When the user has *control* access to a resource owned by someone else:

```dart
ElevatedButton(
child: const Text('Add/Delete Permissions from an External File'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GrantPermissionUi(
resourceName: 'my-data-file.ttl',
isExternalRes: true,
ownerWebId: ownerWebId,
granterWebId: granterWebId,
child: ReturnPage(),
),
),
),
)
```

## View Permission UI Example

The `SharedResourcesUi` widget displays the resources that have been
shared with the current user's POD by others.

### View all shared resources

```dart
ElevatedButton(
child: const Text('View Resources your WebID have access to'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SharedResourcesUi(
child: ReturnPage(),
),
),
),
)
```

### View a specific shared resource

```dart
ElevatedButton(
child: const Text('View access to specific Resource'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SharedResourcesUi(
fileName: 'my-data-file.ttl',
sourceWebId:
'https://pods.solidcommunity.au/john-doe/profile/card#me',
child: ReturnPage(),
),
),
),
)
```

## Authentication and Login Detection

SolidUI provides dynamic login status detection and management through
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependency_overrides:
solidpod:
git:
url: https://github.com/anusii/solidpod.git
ref: dev
ref: tony/59_ui_migration
solidui:
path: ..

Expand Down
21 changes: 21 additions & 0 deletions lib/solidui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export 'src/models/snackbar_config.dart';
export 'src/utils/file_operations.dart';
export 'src/utils/is_text_file.dart';
export 'src/utils/solid_file_operations.dart';
export 'src/utils/is_phone.dart';
export 'src/utils/solid_alert.dart';
export 'src/utils/solid_notifications.dart';
export 'src/utils/solid_pod_helpers.dart'
Expand All @@ -108,6 +109,26 @@ export 'src/widgets/solid_format_info_card.dart';

export 'src/widgets/build_message_container.dart';

export 'src/widgets/app_bar.dart';
export 'src/widgets/file_explorer.dart';
export 'src/widgets/group_webid_input.dart';
export 'src/widgets/ind_webid_input.dart';
export 'src/widgets/ind_webid_input_screen.dart';
export 'src/widgets/permission_checkbox.dart';
export 'src/widgets/shared_resources_table.dart';

export 'src/widgets/grant_permission_ui.dart';
export 'src/widgets/shared_resources_ui.dart';
export 'src/widgets/permission_table.dart';
export 'src/widgets/grant_permission_form.dart';
export 'src/widgets/select_recipients.dart';
export 'src/widgets/show_selected_recipients.dart';
export 'src/widgets/revoke_permission_button.dart';
export 'src/widgets/share_resource_button.dart';

export 'src/widgets/permission_history.dart';
export 'src/widgets/grant_permission_helpers_ui.dart';

export 'src/constants/initial_setup.dart';
export 'src/screens/initial_setup_screen.dart';
export 'src/screens/initial_setup_screen_body.dart';
Expand Down
49 changes: 49 additions & 0 deletions lib/src/utils/is_phone.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/// Check if we are running on a mobile device (and not a browser).
///
// Time-stamp: <Saturday 2025-08-02 21:01:01 +1000 Jess Moore>
///
/// Copyright (C) 2024-2025, Software Innovation Institute, ANU.
///
/// Licensed under the MIT License (the "License").
///
/// License: https://choosealicense.com/licenses/mit/.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
///
/// Authors: Jess Moore

library;

import 'package:flutter/foundation.dart'
show kIsWeb, defaultTargetPlatform, TargetPlatform;

/// Checks the platform type to determine whether running on
/// a mobile device.
///
/// Returns true if running on iOS or Android.
/// Returns false on Flutter Web or desktop platforms.

bool isPhone() {
if (kIsWeb) {
return false;
}

return defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.android;
}
75 changes: 75 additions & 0 deletions lib/src/widgets/app_bar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/// A default app bar.
///
// Time-stamp: <Sunday 2024-07-11 12:55:00 +1000 Anushka Vidange>
///
/// Copyright (C) 2024-2025, Software Innovation Institute, ANU.
///
/// Licensed under the MIT License (the "License").
///
/// License: https://choosealicense.com/licenses/mit/.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
///
/// Authors: Anushka Vidanage, Ashley Tang

library;

import 'package:flutter/material.dart';

import 'package:solidui/src/widgets/solid_login_helper.dart'
show pushReplacement;

/// A default app bar that is used when user does not define an app bar for
/// the UI
PreferredSizeWidget defaultAppBar(
BuildContext context,
String title,
Color backgroundColor,
Widget child, {
VoidCallback? onNavigateBack,
bool Function()? getResult,
}) {
return AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
// Call the callback if provided.

onNavigateBack?.call();

if (getResult != null) {
// Pop with result from callback.

Navigator.pop(context, getResult());
} else {
// Use the original pushReplacement behaviour.

pushReplacement(context, child);

// Navigator.pushReplacement(
// context,
// MaterialPageRoute(builder: (context) => child),
// );
}
},
),
backgroundColor: backgroundColor,
title: Text(title),
);
}
Loading