linked-data-browser 0.0.6 → 0.0.8-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +2 -0
- package/.eslintrc.js +1 -0
- package/.ldo/profile.shapeTypes.ts +18 -18
- package/.ldo/profile.typings.ts +17 -17
- package/app/index.tsx +3 -0
- package/babel.config.js +9 -1
- package/components/DataBrowser.tsx +9 -19
- package/components/DataBrowserContext.ts +24 -0
- package/components/TargetResourceProvider.tsx +1 -1
- package/components/ThemeProvider.tsx +2 -4
- package/components/common/LoadingBar.tsx +11 -1
- package/components/common/ProfileAvatar.tsx +6 -9
- package/components/nav/Layout.tsx +20 -4
- package/components/nav/header/AddressBox.tsx +104 -48
- package/components/nav/header/AvatarMenu.tsx +44 -12
- package/components/nav/header/Header.tsx +26 -19
- package/components/nav/header/SignInMenu.tsx +63 -36
- package/components/nav/header/ThemeToggleMenu.tsx +21 -9
- package/components/nav/header/ViewMenu.tsx +79 -71
- package/components/sharing/AccessDropdown.tsx +18 -7
- package/components/sharing/CopyLink.tsx +15 -3
- package/components/sharing/PermissionRow.tsx +17 -2
- package/components/sharing/SharingModal.tsx +30 -3
- package/components/sharing/WacRuleForm.tsx +12 -3
- package/components/sharing/agentPermissions/AgentInformation.tsx +18 -6
- package/components/sharing/agentPermissions/AgentInput.tsx +21 -6
- package/components/sharing/agentPermissions/AgentPermissionRow.tsx +24 -6
- package/components/ui/accordion.tsx +1 -1
- package/components/ui/alert.tsx +62 -46
- package/components/ui/avatar.tsx +38 -13
- package/components/ui/badge.tsx +63 -48
- package/components/ui/button.tsx +226 -108
- package/components/ui/card.tsx +53 -38
- package/components/ui/checkbox.tsx +53 -16
- package/components/ui/context-menu.tsx +4 -4
- package/components/ui/dialog.tsx +116 -65
- package/components/ui/dropdown-menu.tsx +304 -105
- package/components/ui/icon.tsx +23 -0
- package/components/ui/input-dropdown.tsx +42 -5
- package/components/ui/input.tsx +85 -22
- package/components/ui/label.tsx +16 -7
- package/components/ui/menubar.tsx +4 -4
- package/components/ui/navigation-menu.tsx +157 -90
- package/components/ui/progress.tsx +38 -24
- package/components/ui/select.tsx +139 -67
- package/components/ui/separator.tsx +22 -7
- package/components/ui/skeleton.tsx +14 -11
- package/components/ui/switch.tsx +82 -37
- package/components/ui/table.tsx +57 -35
- package/components/ui/tabs.tsx +66 -35
- package/components/ui/text.tsx +221 -30
- package/components/ui/textarea.tsx +34 -10
- package/components/ui/typography.tsx +94 -65
- package/components/useViewContext.tsx +8 -8
- package/global.css +93 -3
- package/metro.config.js +21 -3
- package/package.json +6 -9
- package/resourceViews/Container/ContainerConfig.tsx +1 -1
- package/resourceViews/Container/ContainerView.tsx +63 -25
- package/resourceViews/Profile/ProfileConfig.tsx +3 -3
- package/resourceViews/Profile/ProfileKnows.tsx +20 -11
- package/resourceViews/Profile/ProfileView.tsx +23 -6
- package/resourceViews/RawCode/RawCodeConfig.tsx +1 -1
- package/resourceViews/RawCode/RawCodeView.tsx +20 -6
- package/components.json +0 -7
- package/lib/icons/ArrowRight.tsx +0 -4
- package/lib/icons/Check.tsx +0 -4
- package/lib/icons/ChevronDown.tsx +0 -4
- package/lib/icons/ChevronRight.tsx +0 -4
- package/lib/icons/ChevronUp.tsx +0 -4
- package/lib/icons/ChevronsRight.tsx +0 -4
- package/lib/icons/CircleSlash.tsx +0 -4
- package/lib/icons/CircleX.tsx +0 -4
- package/lib/icons/Code.tsx +0 -4
- package/lib/icons/EllipsisVertical.tsx +0 -4
- package/lib/icons/EyeOff.tsx +0 -4
- package/lib/icons/File.tsx +0 -4
- package/lib/icons/Fingerprint.tsx +0 -4
- package/lib/icons/Folder.tsx +0 -4
- package/lib/icons/Folders.tsx +0 -4
- package/lib/icons/Info.tsx +0 -4
- package/lib/icons/Link.tsx +0 -4
- package/lib/icons/Loader.tsx +0 -4
- package/lib/icons/LogOut.tsx +0 -4
- package/lib/icons/MonitorSmartphone.tsx +0 -4
- package/lib/icons/MoonStar.tsx +0 -4
- package/lib/icons/OctagonX.tsx +0 -4
- package/lib/icons/Plus.tsx +0 -4
- package/lib/icons/RefreshCw.tsx +0 -4
- package/lib/icons/Save.tsx +0 -4
- package/lib/icons/ShieldX.tsx +0 -4
- package/lib/icons/Sun.tsx +0 -4
- package/lib/icons/TextCursorInput.tsx +0 -4
- package/lib/icons/Trash.tsx +0 -4
- package/lib/icons/User.tsx +0 -4
- package/lib/icons/UserPlus.tsx +0 -4
- package/lib/icons/Users.tsx +0 -4
- package/lib/icons/ViewIcon.tsx +0 -4
- package/lib/icons/X.tsx +0 -4
- package/lib/icons/iconWithClassName.ts +0 -14
- package/lib/utils.ts +0 -6
- package/nativewind-env.d.ts +0 -1
- package/tailwind.config.js +0 -69
package/.env
ADDED
package/.eslintrc.js
CHANGED
|
@@ -2,12 +2,12 @@ import { ShapeType } from "@ldo/ldo";
|
|
|
2
2
|
import { profileSchema } from "./profile.schema";
|
|
3
3
|
import { profileContext } from "./profile.context";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
SolidProfile,
|
|
6
|
+
Address,
|
|
7
|
+
Email,
|
|
8
|
+
PhoneNumber,
|
|
9
|
+
TrustedApp,
|
|
10
|
+
RSAPublicKey,
|
|
11
11
|
} from "./profile.typings";
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -17,54 +17,54 @@ import {
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* SolidProfile ShapeType
|
|
21
21
|
*/
|
|
22
|
-
export const
|
|
22
|
+
export const SolidProfileShapeType: ShapeType<SolidProfile> = {
|
|
23
23
|
schema: profileSchema,
|
|
24
24
|
shape: "https://shaperepo.com/schemas/solidProfile#SolidProfileShape",
|
|
25
25
|
context: profileContext,
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Address ShapeType
|
|
30
30
|
*/
|
|
31
|
-
export const
|
|
31
|
+
export const AddressShapeType: ShapeType<Address> = {
|
|
32
32
|
schema: profileSchema,
|
|
33
33
|
shape: "https://shaperepo.com/schemas/solidProfile#AddressShape",
|
|
34
34
|
context: profileContext,
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* Email ShapeType
|
|
39
39
|
*/
|
|
40
|
-
export const
|
|
40
|
+
export const EmailShapeType: ShapeType<Email> = {
|
|
41
41
|
schema: profileSchema,
|
|
42
42
|
shape: "https://shaperepo.com/schemas/solidProfile#EmailShape",
|
|
43
43
|
context: profileContext,
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
47
|
+
* PhoneNumber ShapeType
|
|
48
48
|
*/
|
|
49
|
-
export const
|
|
49
|
+
export const PhoneNumberShapeType: ShapeType<PhoneNumber> = {
|
|
50
50
|
schema: profileSchema,
|
|
51
51
|
shape: "https://shaperepo.com/schemas/solidProfile#PhoneNumberShape",
|
|
52
52
|
context: profileContext,
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
56
|
+
* TrustedApp ShapeType
|
|
57
57
|
*/
|
|
58
|
-
export const
|
|
58
|
+
export const TrustedAppShapeType: ShapeType<TrustedApp> = {
|
|
59
59
|
schema: profileSchema,
|
|
60
60
|
shape: "https://shaperepo.com/schemas/solidProfile#TrustedAppShape",
|
|
61
61
|
context: profileContext,
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
65
|
+
* RSAPublicKey ShapeType
|
|
66
66
|
*/
|
|
67
|
-
export const
|
|
67
|
+
export const RSAPublicKeyShapeType: ShapeType<RSAPublicKey> = {
|
|
68
68
|
schema: profileSchema,
|
|
69
69
|
shape: "https://shaperepo.com/schemas/solidProfile#RSAPublicKeyShape",
|
|
70
70
|
context: profileContext,
|
package/.ldo/profile.typings.ts
CHANGED
|
@@ -7,9 +7,9 @@ import { LdoJsonldContext, LdSet } from "@ldo/ldo";
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* SolidProfile Type
|
|
11
11
|
*/
|
|
12
|
-
export interface
|
|
12
|
+
export interface SolidProfile {
|
|
13
13
|
"@id"?: string;
|
|
14
14
|
"@context"?: LdoJsonldContext;
|
|
15
15
|
/**
|
|
@@ -34,11 +34,11 @@ export interface SolidProfileShape {
|
|
|
34
34
|
/**
|
|
35
35
|
* The person's street address.
|
|
36
36
|
*/
|
|
37
|
-
hasAddress?: LdSet<
|
|
37
|
+
hasAddress?: LdSet<Address>;
|
|
38
38
|
/**
|
|
39
39
|
* The person's email.
|
|
40
40
|
*/
|
|
41
|
-
hasEmail?: LdSet<
|
|
41
|
+
hasEmail?: LdSet<Email>;
|
|
42
42
|
/**
|
|
43
43
|
* A link to the person's photo
|
|
44
44
|
*/
|
|
@@ -52,7 +52,7 @@ export interface SolidProfileShape {
|
|
|
52
52
|
/**
|
|
53
53
|
* Person's telephone number
|
|
54
54
|
*/
|
|
55
|
-
hasTelephone?: LdSet<
|
|
55
|
+
hasTelephone?: LdSet<PhoneNumber>;
|
|
56
56
|
/**
|
|
57
57
|
* An alternative way to define a person's telephone number using a string
|
|
58
58
|
*/
|
|
@@ -68,11 +68,11 @@ export interface SolidProfileShape {
|
|
|
68
68
|
/**
|
|
69
69
|
* A list of app origins that are trusted by this user
|
|
70
70
|
*/
|
|
71
|
-
trustedApp?: LdSet<
|
|
71
|
+
trustedApp?: LdSet<TrustedApp>;
|
|
72
72
|
/**
|
|
73
73
|
* A list of RSA public keys that are associated with private keys the user holds.
|
|
74
74
|
*/
|
|
75
|
-
key?: LdSet<
|
|
75
|
+
key?: LdSet<RSAPublicKey>;
|
|
76
76
|
/**
|
|
77
77
|
* The user's LDP inbox to which apps can post notifications
|
|
78
78
|
*/
|
|
@@ -118,9 +118,9 @@ export interface SolidProfileShape {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
/**
|
|
121
|
-
*
|
|
121
|
+
* Address Type
|
|
122
122
|
*/
|
|
123
|
-
export interface
|
|
123
|
+
export interface Address {
|
|
124
124
|
"@id"?: string;
|
|
125
125
|
"@context"?: LdoJsonldContext;
|
|
126
126
|
/**
|
|
@@ -146,9 +146,9 @@ export interface AddressShape {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
|
-
*
|
|
149
|
+
* Email Type
|
|
150
150
|
*/
|
|
151
|
-
export interface
|
|
151
|
+
export interface Email {
|
|
152
152
|
"@id"?: string;
|
|
153
153
|
"@context"?: LdoJsonldContext;
|
|
154
154
|
/**
|
|
@@ -198,9 +198,9 @@ export interface EmailShape {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
|
-
*
|
|
201
|
+
* PhoneNumber Type
|
|
202
202
|
*/
|
|
203
|
-
export interface
|
|
203
|
+
export interface PhoneNumber {
|
|
204
204
|
"@id"?: string;
|
|
205
205
|
"@context"?: LdoJsonldContext;
|
|
206
206
|
/**
|
|
@@ -250,9 +250,9 @@ export interface PhoneNumberShape {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
/**
|
|
253
|
-
*
|
|
253
|
+
* TrustedApp Type
|
|
254
254
|
*/
|
|
255
|
-
export interface
|
|
255
|
+
export interface TrustedApp {
|
|
256
256
|
"@id"?: string;
|
|
257
257
|
"@context"?: LdoJsonldContext;
|
|
258
258
|
/**
|
|
@@ -281,9 +281,9 @@ export interface TrustedAppShape {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
/**
|
|
284
|
-
*
|
|
284
|
+
* RSAPublicKey Type
|
|
285
285
|
*/
|
|
286
|
-
export interface
|
|
286
|
+
export interface RSAPublicKey {
|
|
287
287
|
"@id"?: string;
|
|
288
288
|
"@context"?: LdoJsonldContext;
|
|
289
289
|
/**
|
package/app/index.tsx
CHANGED
|
@@ -12,6 +12,8 @@ export function Screen() {
|
|
|
12
12
|
? 'server-ui'
|
|
13
13
|
: 'standalone-app';
|
|
14
14
|
|
|
15
|
+
const defaultIssuer = process.env.EXPO_PUBLIC_DEFAULT_ISSUER;
|
|
16
|
+
|
|
15
17
|
return (
|
|
16
18
|
<SafeAreaProvider>
|
|
17
19
|
<StatusBar />
|
|
@@ -20,6 +22,7 @@ export function Screen() {
|
|
|
20
22
|
mode={mode}
|
|
21
23
|
renderHomepage={() => <Text>Hopepage</Text>}
|
|
22
24
|
renderLogo={() => <Text>Logo</Text>}
|
|
25
|
+
defaultIssuer={defaultIssuer}
|
|
23
26
|
/>
|
|
24
27
|
</SafeAreaProvider>
|
|
25
28
|
);
|
package/babel.config.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
module.exports = function (api) {
|
|
2
2
|
api.cache(true);
|
|
3
3
|
return {
|
|
4
|
-
presets: [
|
|
4
|
+
presets: [
|
|
5
|
+
[
|
|
6
|
+
'babel-preset-expo',
|
|
7
|
+
{
|
|
8
|
+
unstable_transformProfile: 'hermes-canary',
|
|
9
|
+
},
|
|
10
|
+
],
|
|
11
|
+
],
|
|
12
|
+
plugins: ['@babel/plugin-syntax-import-meta'],
|
|
5
13
|
};
|
|
6
14
|
};
|
|
@@ -1,31 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
2
|
import { BrowserSolidLdoProvider } from '@ldo/solid-react';
|
|
3
3
|
import React, { FunctionComponent } from 'react';
|
|
4
4
|
import { Layout } from './nav/Layout';
|
|
5
5
|
import { PortalHost } from '@rn-primitives/portal';
|
|
6
6
|
import { TargetResourceProvider } from './TargetResourceProvider';
|
|
7
|
-
import { ResourceViewConfig } from './ResourceView';
|
|
8
7
|
import { NotifierWrapper } from 'react-native-notifier';
|
|
9
8
|
import { Platform } from 'react-native';
|
|
10
9
|
import { ThemeProvider } from './ThemeProvider';
|
|
10
|
+
import {
|
|
11
|
+
DataBrowserConfig,
|
|
12
|
+
DataBrowserConfigContext,
|
|
13
|
+
DataBrowserConfigProps,
|
|
14
|
+
} from './DataBrowserContext';
|
|
11
15
|
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
defaultIssuer?: string;
|
|
16
|
-
origin?: string;
|
|
17
|
-
renderHomepage?: () => ReactNode;
|
|
18
|
-
renderLogo?: () => ReactNode;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// @ts-ignore This will be filled in once the component mounts
|
|
22
|
-
export const DataBrowserConfigContext = createContext<DataBrowserConfig>({});
|
|
23
|
-
|
|
24
|
-
export function useDataBrowserConfig() {
|
|
25
|
-
return useContext(DataBrowserConfigContext);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const DataBrowser: FunctionComponent<DataBrowserConfig> = (props) => {
|
|
16
|
+
export const DataBrowser: FunctionComponent<DataBrowserConfigProps> = (
|
|
17
|
+
props,
|
|
18
|
+
) => {
|
|
29
19
|
const providerProps = useMemo<DataBrowserConfig>(() => {
|
|
30
20
|
return {
|
|
31
21
|
origin:
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createContext, ReactNode, useContext } from 'react';
|
|
2
|
+
import { ResourceViewConfig } from './ResourceView';
|
|
3
|
+
|
|
4
|
+
export interface DataBrowserConfigProps {
|
|
5
|
+
views: ResourceViewConfig[];
|
|
6
|
+
mode: 'standalone-app' | 'server-ui';
|
|
7
|
+
defaultIssuer?: string;
|
|
8
|
+
origin?: string;
|
|
9
|
+
renderHomepage?: () => ReactNode;
|
|
10
|
+
renderLogo?: () => ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DataBrowserConfig extends DataBrowserConfigProps {
|
|
14
|
+
defaultIssuer: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const DataBrowserConfigContext = createContext<DataBrowserConfig>(
|
|
18
|
+
// @ts-ignore This will be filled in once the component mounts
|
|
19
|
+
{},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export function useDataBrowserConfig() {
|
|
23
|
+
return useContext(DataBrowserConfigContext);
|
|
24
|
+
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from 'react';
|
|
8
8
|
import { SolidLeaf, SolidContainer } from '@ldo/connected-solid';
|
|
9
9
|
import { InvalidIdentifierResource } from '@ldo/connected';
|
|
10
|
-
import { useDataBrowserConfig } from './
|
|
10
|
+
import { useDataBrowserConfig } from './DataBrowserContext';
|
|
11
11
|
import { useResource } from '@ldo/solid-react';
|
|
12
12
|
import { Platform } from 'react-native';
|
|
13
13
|
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
Theme,
|
|
18
18
|
} from '@react-navigation/native';
|
|
19
19
|
import { NAV_THEME } from '../lib/constants';
|
|
20
|
-
import { useColorScheme } from 'nativewind';
|
|
21
20
|
import { setAndroidNavigationBar } from '../lib/android-navigation-bar';
|
|
22
21
|
|
|
23
22
|
const COLOR_SCHEME_KEY = 'colorScheme';
|
|
@@ -57,14 +56,14 @@ const usePlatformSpecificSetup = Platform.select({
|
|
|
57
56
|
export const ThemeProvider: FunctionComponent<PropsWithChildren> = ({
|
|
58
57
|
children,
|
|
59
58
|
}) => {
|
|
60
|
-
const
|
|
59
|
+
const [colorScheme, setColorScheme] = useState<ColorSchemeName>();
|
|
61
60
|
const [loadingColorScheme, setLoadingColorScheme] = useState(true);
|
|
62
61
|
|
|
63
62
|
usePlatformSpecificSetup();
|
|
64
63
|
|
|
65
64
|
useEffect(() => {
|
|
66
65
|
const lookupCurColorScheme = async () => {
|
|
67
|
-
setColorScheme(Appearance.getColorScheme() ?? '
|
|
66
|
+
setColorScheme(Appearance.getColorScheme() ?? 'light');
|
|
68
67
|
const storedColorSchemeName: ColorSchemeName =
|
|
69
68
|
((await AsyncStorage.getItem(COLOR_SCHEME_KEY)) as ColorSchemeName) ||
|
|
70
69
|
Appearance.getColorScheme();
|
|
@@ -74,7 +73,6 @@ export const ThemeProvider: FunctionComponent<PropsWithChildren> = ({
|
|
|
74
73
|
setLoadingColorScheme(false);
|
|
75
74
|
};
|
|
76
75
|
lookupCurColorScheme();
|
|
77
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
76
|
}, []);
|
|
79
77
|
|
|
80
78
|
const context = useMemo(
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { useTheme } from '@react-navigation/native';
|
|
3
3
|
import { FunctionComponent } from 'react';
|
|
4
4
|
import { Bar } from 'react-native-progress';
|
|
5
|
+
import { StyleSheet } from 'react-native';
|
|
5
6
|
|
|
6
7
|
interface LoadingBarProps {
|
|
7
8
|
isLoading: boolean;
|
|
@@ -21,7 +22,16 @@ export const LoadingBar: FunctionComponent<LoadingBarProps> = ({
|
|
|
21
22
|
borderWidth={0}
|
|
22
23
|
borderRadius={0}
|
|
23
24
|
width={null}
|
|
24
|
-
|
|
25
|
+
style={styles.bar}
|
|
25
26
|
/>
|
|
26
27
|
);
|
|
27
28
|
};
|
|
29
|
+
|
|
30
|
+
const styles = StyleSheet.create({
|
|
31
|
+
bar: {
|
|
32
|
+
position: 'absolute',
|
|
33
|
+
top: 0,
|
|
34
|
+
left: 0,
|
|
35
|
+
right: 0,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { SolidProfile } from '../../.ldo/profile.typings';
|
|
3
3
|
import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
|
|
4
4
|
import { Text } from '../ui/text';
|
|
5
|
-
import { User } from '
|
|
5
|
+
import { User } from 'lucide-react-native';
|
|
6
6
|
import { FunctionComponent } from 'react';
|
|
7
7
|
|
|
8
8
|
interface ProfileAvatarProps {
|
|
9
|
-
profile?:
|
|
10
|
-
|
|
9
|
+
profile?: SolidProfile;
|
|
10
|
+
style?: any;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const ProfileAvatar: FunctionComponent<ProfileAvatarProps> = ({
|
|
14
14
|
profile,
|
|
15
|
-
|
|
15
|
+
style,
|
|
16
16
|
}) => (
|
|
17
|
-
<Avatar
|
|
18
|
-
alt={profile?.fn ? `${profile.fn}'s Avatar` : ''}
|
|
19
|
-
className={className}
|
|
20
|
-
>
|
|
17
|
+
<Avatar alt={profile?.fn ? `${profile.fn}'s Avatar` : ''} style={style}>
|
|
21
18
|
<AvatarImage source={{ uri: profile?.hasPhoto?.['@id'] }} />
|
|
22
19
|
<AvatarFallback>
|
|
23
20
|
<Text>
|
|
@@ -7,11 +7,12 @@ import React, {
|
|
|
7
7
|
import { ResourceViewConfig } from '../ResourceView';
|
|
8
8
|
|
|
9
9
|
import { Header } from './header/Header';
|
|
10
|
-
import { View } from 'react-native';
|
|
10
|
+
import { View, StyleSheet } from 'react-native';
|
|
11
11
|
import { useViewContext, ViewContextProvider } from '../useViewContext';
|
|
12
12
|
import { DialogProvider } from './DialogProvider';
|
|
13
13
|
import { useSolidAuth } from '@ldo/solid-react';
|
|
14
14
|
import { SharingModalProvider } from '../sharing/SharingModal';
|
|
15
|
+
import { useTheme } from '@react-navigation/native';
|
|
15
16
|
|
|
16
17
|
export const ValidViewContext = createContext<{
|
|
17
18
|
validViews: ResourceViewConfig[];
|
|
@@ -22,6 +23,7 @@ export const ValidViewContext = createContext<{
|
|
|
22
23
|
|
|
23
24
|
export const Layout: FunctionComponent = () => {
|
|
24
25
|
const { ranInitialAuthCheck } = useSolidAuth();
|
|
26
|
+
const { colors } = useTheme();
|
|
25
27
|
|
|
26
28
|
if (!ranInitialAuthCheck) {
|
|
27
29
|
return <></>;
|
|
@@ -31,9 +33,13 @@ export const Layout: FunctionComponent = () => {
|
|
|
31
33
|
<DialogProvider>
|
|
32
34
|
<ViewContextProvider>
|
|
33
35
|
<SharingModalProvider>
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
<View
|
|
37
|
+
style={[styles.container, { backgroundColor: colors.background }]}
|
|
38
|
+
>
|
|
39
|
+
<Header />
|
|
40
|
+
<View style={styles.contentView}>
|
|
41
|
+
<RenderView />
|
|
42
|
+
</View>
|
|
37
43
|
</View>
|
|
38
44
|
</SharingModalProvider>
|
|
39
45
|
</ViewContextProvider>
|
|
@@ -55,3 +61,13 @@ export const RenderView: FunctionComponent = () => {
|
|
|
55
61
|
const CurView = curViewConfig.view;
|
|
56
62
|
return <CurView />;
|
|
57
63
|
};
|
|
64
|
+
|
|
65
|
+
const styles = StyleSheet.create({
|
|
66
|
+
container: {
|
|
67
|
+
flex: 1,
|
|
68
|
+
},
|
|
69
|
+
contentView: {
|
|
70
|
+
flex: 1,
|
|
71
|
+
zIndex: 0,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import React, { useEffect, useMemo } from 'react';
|
|
2
2
|
import { FunctionComponent, useState } from 'react';
|
|
3
|
-
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { TouchableOpacity, View, StyleSheet, ScrollView } from 'react-native';
|
|
4
4
|
import { Input } from '../../ui/input';
|
|
5
|
-
import { ChevronRight } from '
|
|
6
|
-
import { ChevronsRight } from '
|
|
7
|
-
import { TextCursorInput } from '
|
|
8
|
-
import { RefreshCw } from '
|
|
9
|
-
import { ArrowRight } from '
|
|
5
|
+
import { ChevronRight } from 'lucide-react-native';
|
|
6
|
+
import { ChevronsRight } from 'lucide-react-native';
|
|
7
|
+
import { TextCursorInput } from 'lucide-react-native';
|
|
8
|
+
import { RefreshCw } from 'lucide-react-native';
|
|
9
|
+
import { ArrowRight } from 'lucide-react-native';
|
|
10
10
|
import { Button } from '../../../components/ui/button';
|
|
11
11
|
import { Text } from '../../ui/text';
|
|
12
12
|
import { useTargetResource } from '../../TargetResourceProvider';
|
|
13
|
+
import { useTheme } from '@react-navigation/native';
|
|
14
|
+
import { Icon } from '../../../components/ui/icon';
|
|
13
15
|
|
|
14
16
|
export const AddressBox: FunctionComponent = () => {
|
|
15
17
|
const [isTextMode, setIsTextMode] = useState(false);
|
|
16
18
|
const { targetUri, refresh, navigateTo, targetResource } =
|
|
17
19
|
useTargetResource();
|
|
20
|
+
const { colors } = useTheme();
|
|
18
21
|
|
|
19
22
|
const [textBoxValue, setTextBoxValue] = useState(targetUri ?? '');
|
|
20
23
|
useEffect(() => {
|
|
@@ -51,9 +54,9 @@ export const AddressBox: FunctionComponent = () => {
|
|
|
51
54
|
}, [targetUri]);
|
|
52
55
|
|
|
53
56
|
return (
|
|
54
|
-
<View
|
|
57
|
+
<View style={styles.container}>
|
|
55
58
|
<Input
|
|
56
|
-
|
|
59
|
+
style={[styles.input, { backgroundColor: colors.border }]}
|
|
57
60
|
onFocus={() => setIsTextMode(true)}
|
|
58
61
|
onBlur={() => setTimeout(() => setIsTextMode(false), 100)}
|
|
59
62
|
onChangeText={setTextBoxValue}
|
|
@@ -66,22 +69,41 @@ export const AddressBox: FunctionComponent = () => {
|
|
|
66
69
|
/>
|
|
67
70
|
<Button
|
|
68
71
|
variant="secondary"
|
|
69
|
-
|
|
72
|
+
style={styles.leftButton}
|
|
70
73
|
onPress={() => setIsTextMode((val) => !val)}
|
|
71
|
-
iconLeft={
|
|
72
|
-
|
|
73
|
-
<ChevronsRight size={20} />
|
|
74
|
-
) : (
|
|
75
|
-
<TextCursorInput size={20} />
|
|
76
|
-
)
|
|
77
|
-
}
|
|
74
|
+
iconLeft={isTextMode ? ChevronsRight : TextCursorInput}
|
|
75
|
+
textStyle={styles.buttonText}
|
|
78
76
|
/>
|
|
77
|
+
<ScrollView
|
|
78
|
+
style={styles.breadcrumbContainer}
|
|
79
|
+
contentContainerStyle={styles.breadcrumbContentContainer}
|
|
80
|
+
pointerEvents="none"
|
|
81
|
+
horizontal
|
|
82
|
+
>
|
|
83
|
+
{!isTextMode &&
|
|
84
|
+
breadcrumbInfo.map((item, index) => (
|
|
85
|
+
<View style={styles.breadcrumbItem} key={item.uri}>
|
|
86
|
+
<TouchableOpacity onPress={() => navigateTo(item.uri)}>
|
|
87
|
+
<View pointerEvents="auto">
|
|
88
|
+
<Text style={styles.breadcrumbText} size="sm">
|
|
89
|
+
{item.name}
|
|
90
|
+
</Text>
|
|
91
|
+
</View>
|
|
92
|
+
</TouchableOpacity>
|
|
93
|
+
{index !== breadcrumbInfo.length - 1 ? (
|
|
94
|
+
<Icon icon={ChevronRight} style={styles.chevron} />
|
|
95
|
+
) : (
|
|
96
|
+
<View style={styles.spacer} />
|
|
97
|
+
)}
|
|
98
|
+
</View>
|
|
99
|
+
))}
|
|
100
|
+
</ScrollView>
|
|
79
101
|
{(() => {
|
|
80
102
|
const shouldRefresh = targetUri === textBoxValue || !isTextMode;
|
|
81
103
|
return (
|
|
82
104
|
<Button
|
|
83
105
|
variant="secondary"
|
|
84
|
-
|
|
106
|
+
style={styles.rightButton}
|
|
85
107
|
onPressIn={() => {
|
|
86
108
|
if (shouldRefresh) {
|
|
87
109
|
refresh();
|
|
@@ -89,39 +111,73 @@ export const AddressBox: FunctionComponent = () => {
|
|
|
89
111
|
navigateTo(textBoxValue);
|
|
90
112
|
}
|
|
91
113
|
}}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</Text>
|
|
100
|
-
</Button>
|
|
114
|
+
iconLeft={
|
|
115
|
+
shouldRefresh || targetResource?.isLoading()
|
|
116
|
+
? RefreshCw
|
|
117
|
+
: ArrowRight
|
|
118
|
+
}
|
|
119
|
+
textStyle={styles.buttonText}
|
|
120
|
+
/>
|
|
101
121
|
);
|
|
102
122
|
})()}
|
|
103
|
-
<View
|
|
104
|
-
className="absolute top-0 left-0 right-0 bottom-0 flex-row-reverse items-center ml-10 mr-10 overflow-x-auto scrollbar-hide [direction:rtl]"
|
|
105
|
-
pointerEvents="none"
|
|
106
|
-
>
|
|
107
|
-
{!isTextMode &&
|
|
108
|
-
breadcrumbInfo.map((item, index) => (
|
|
109
|
-
<View className="flex-row" key={item.uri}>
|
|
110
|
-
{index !== breadcrumbInfo.length - 1 ? (
|
|
111
|
-
<ChevronRight className="w-4 h-4 mr-0.5 mt-0.5 text-gray-500" />
|
|
112
|
-
) : (
|
|
113
|
-
<View className="w-2" />
|
|
114
|
-
)}
|
|
115
|
-
<TouchableOpacity onPress={() => navigateTo(item.uri)}>
|
|
116
|
-
<View pointerEvents="auto">
|
|
117
|
-
<Text className="mr-0.5 underline" size="sm">
|
|
118
|
-
{item.name}
|
|
119
|
-
</Text>
|
|
120
|
-
</View>
|
|
121
|
-
</TouchableOpacity>
|
|
122
|
-
</View>
|
|
123
|
-
))}
|
|
124
|
-
</View>
|
|
125
123
|
</View>
|
|
126
124
|
);
|
|
127
125
|
};
|
|
126
|
+
|
|
127
|
+
const styles = StyleSheet.create({
|
|
128
|
+
container: {
|
|
129
|
+
flex: 1,
|
|
130
|
+
height: 40,
|
|
131
|
+
},
|
|
132
|
+
input: {
|
|
133
|
+
flex: 1,
|
|
134
|
+
borderWidth: 0,
|
|
135
|
+
paddingHorizontal: 40,
|
|
136
|
+
height: 40,
|
|
137
|
+
fontSize: 14,
|
|
138
|
+
},
|
|
139
|
+
leftButton: {
|
|
140
|
+
position: 'absolute',
|
|
141
|
+
left: 0,
|
|
142
|
+
width: 40,
|
|
143
|
+
height: 40,
|
|
144
|
+
},
|
|
145
|
+
rightButton: {
|
|
146
|
+
position: 'absolute',
|
|
147
|
+
right: 0,
|
|
148
|
+
width: 40,
|
|
149
|
+
height: 40,
|
|
150
|
+
},
|
|
151
|
+
breadcrumbContainer: {
|
|
152
|
+
position: 'absolute',
|
|
153
|
+
top: 0,
|
|
154
|
+
left: 0,
|
|
155
|
+
right: 0,
|
|
156
|
+
bottom: 0,
|
|
157
|
+
marginLeft: 40,
|
|
158
|
+
marginRight: 40,
|
|
159
|
+
},
|
|
160
|
+
breadcrumbContentContainer: {
|
|
161
|
+
flexDirection: 'row',
|
|
162
|
+
alignItems: 'center',
|
|
163
|
+
},
|
|
164
|
+
breadcrumbItem: {
|
|
165
|
+
flexDirection: 'row',
|
|
166
|
+
},
|
|
167
|
+
chevron: {
|
|
168
|
+
width: 16,
|
|
169
|
+
height: 16,
|
|
170
|
+
marginRight: 2,
|
|
171
|
+
color: 'hsl(var(--muted-foreground))',
|
|
172
|
+
},
|
|
173
|
+
spacer: {
|
|
174
|
+
width: 8,
|
|
175
|
+
},
|
|
176
|
+
breadcrumbText: {
|
|
177
|
+
marginRight: 2,
|
|
178
|
+
textDecorationLine: 'underline',
|
|
179
|
+
},
|
|
180
|
+
buttonText: {
|
|
181
|
+
fontSize: 20,
|
|
182
|
+
},
|
|
183
|
+
});
|