feat: implement permission handling in ModelsScreen and update PermissionMessage component
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text, TouchableOpacity } from 'react-native';
|
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
||||||
import { createStyles } from './styles';
|
|
||||||
import { useTheme } from '../../theme/ThemeProvider';
|
import { useTheme } from '../../theme/ThemeProvider';
|
||||||
|
|
||||||
interface PermissionMessageProps {
|
interface PermissionMessageProps {
|
||||||
@@ -11,24 +10,62 @@ export default function PermissionMessage({
|
|||||||
onRequestPermission,
|
onRequestPermission,
|
||||||
}: PermissionMessageProps) {
|
}: PermissionMessageProps) {
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const styles = createStyles(colors);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.permissionContainer}>
|
<View style={[styles.container, { backgroundColor: colors.background }]}>
|
||||||
<Text style={styles.permissionText}>
|
<Text style={styles.icon}>📁</Text>
|
||||||
📁 Permission requise
|
<Text style={[styles.title, { color: colors.text }]}>
|
||||||
|
Permission requise
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={styles.permissionSubtext}>
|
<Text style={[styles.subtitle, { color: colors.text }]}>
|
||||||
L'application a besoin d'accéder aux fichiers pour lire vos modèles GGUF
|
L'application a besoin d'accéder aux fichiers pour lire vos modèles GGUF.
|
||||||
</Text>
|
</Text>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.permissionButton}
|
style={[styles.button, { backgroundColor: colors.primary }]}
|
||||||
onPress={onRequestPermission}
|
onPress={onRequestPermission}
|
||||||
|
activeOpacity={0.8}
|
||||||
>
|
>
|
||||||
<Text style={styles.permissionButtonText}>
|
<Text style={[styles.buttonText, { color: colors.onPrimary }]}>
|
||||||
Autoriser l'accès aux fichiers
|
Autoriser l'accès aux fichiers
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingHorizontal: 40,
|
||||||
|
gap: 16,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
fontSize: 56,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 22,
|
||||||
|
fontWeight: '700',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
fontSize: 15,
|
||||||
|
textAlign: 'center',
|
||||||
|
opacity: 0.65,
|
||||||
|
lineHeight: 22,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
paddingHorizontal: 28,
|
||||||
|
paddingVertical: 14,
|
||||||
|
borderRadius: 12,
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import type { ModelConfig } from '../../store/types';
|
|||||||
import ModelItem from './ModelItem';
|
import ModelItem from './ModelItem';
|
||||||
import DirectoryPicker from './DirectoryPicker';
|
import DirectoryPicker from './DirectoryPicker';
|
||||||
import DirectoryEditor from './DirectoryEditor';
|
import DirectoryEditor from './DirectoryEditor';
|
||||||
import PermissionMessage from './PermissionMessage';
|
|
||||||
import ModelsList from './ModelsList';
|
import ModelsList from './ModelsList';
|
||||||
import { createStyles } from './styles';
|
import { createStyles } from './styles';
|
||||||
import { useTheme } from '../../theme/ThemeProvider';
|
import { useTheme } from '../../theme/ThemeProvider';
|
||||||
@@ -381,9 +380,6 @@ export default function LocalModelsScreen() {
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{!hasPermission && (
|
|
||||||
<PermissionMessage onRequestPermission={handleRequestPermission} />
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Models List */}
|
{/* Models List */}
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
|
import { AppState } from 'react-native';
|
||||||
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
|
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
|
||||||
|
import { useFocusEffect } from '@react-navigation/native';
|
||||||
import { useTheme } from '../theme/ThemeProvider';
|
import { useTheme } from '../theme/ThemeProvider';
|
||||||
import LocalModelsScreen from './LocalModelsScreen';
|
import LocalModelsScreen from './LocalModelsScreen';
|
||||||
import HuggingFaceModelsScreen from './HuggingFaceModelsScreen';
|
import HuggingFaceModelsScreen from './HuggingFaceModelsScreen';
|
||||||
|
import PermissionMessage from './LocalModelsScreen/PermissionMessage';
|
||||||
|
import {
|
||||||
|
checkStoragePermission,
|
||||||
|
requestStoragePermission,
|
||||||
|
} from '../utils/permissions';
|
||||||
|
|
||||||
export type ModelsTabParamList = {
|
export type ModelsTabParamList = {
|
||||||
LocalModels: undefined;
|
LocalModels: undefined;
|
||||||
@@ -14,6 +21,31 @@ const Tab = createMaterialTopTabNavigator<ModelsTabParamList>();
|
|||||||
export default function ModelsScreen() {
|
export default function ModelsScreen() {
|
||||||
const { colors, scheme } = useTheme();
|
const { colors, scheme } = useTheme();
|
||||||
const isDark = scheme === 'dark';
|
const isDark = scheme === 'dark';
|
||||||
|
const [hasPermission, setHasPermission] = useState(false);
|
||||||
|
|
||||||
|
const checkPerm = useCallback(async () => {
|
||||||
|
const granted = await checkStoragePermission();
|
||||||
|
setHasPermission(granted);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkPerm();
|
||||||
|
const sub = AppState.addEventListener('change', (state) => {
|
||||||
|
if (state === 'active') checkPerm();
|
||||||
|
});
|
||||||
|
return () => sub.remove();
|
||||||
|
}, [checkPerm]);
|
||||||
|
|
||||||
|
useFocusEffect(useCallback(() => { checkPerm(); }, [checkPerm]));
|
||||||
|
|
||||||
|
const handleRequestPermission = async () => {
|
||||||
|
await requestStoragePermission();
|
||||||
|
setTimeout(checkPerm, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!hasPermission) {
|
||||||
|
return <PermissionMessage onRequestPermission={handleRequestPermission} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Navigator
|
<Tab.Navigator
|
||||||
|
|||||||
Reference in New Issue
Block a user