Compare commits

..

13 Commits

Author SHA1 Message Date
David Fessler f4fb7ebe2b
Update README.md 2023-08-05 11:42:58 -04:00
David Fessler c49a0150c9
Update README.md 2023-08-05 11:26:20 -04:00
moist-webDev 6967ffa346 slightly better splash and icon 2023-06-22 21:32:47 -04:00
moist-webDev 3ad28fad8b icon stuff 2023-06-21 22:38:55 -04:00
moist-webDev 1c9f1b9ce2 temp icon and splash screen 2023-06-21 22:02:35 -04:00
moist-webDev 502a5305c2 switched theme functions to nasa instead of raw AsyncStorage 2023-06-21 21:59:27 -04:00
moist-webDev 955b14ee61 delete custom category and all its data 2023-06-21 21:58:26 -04:00
moist-webDev 8333d9a591 remove copilot comments 2023-06-21 21:57:24 -04:00
moist-webDev 112e4127c1 change delete button to lond press only 2023-06-21 21:53:49 -04:00
moist-webDev 13d995edd2 created a table schema for settings 2023-06-21 21:53:03 -04:00
moist-webDev 7918b3d9f9 ability to assign custom id to data entry 2023-06-21 21:52:13 -04:00
moist-webDev 318a17b9be removed uneeded test table 2023-06-21 21:49:56 -04:00
moist-webDev 3baba5b4eb got rid of word garbage on import and export button 2023-06-11 19:59:15 +00:00
14 changed files with 79 additions and 31 deletions

30
App.tsx
View File

@ -15,7 +15,16 @@ import TitleBar from './components/TitleBar';
import db from './lib/client'; import db from './lib/client';
const findTheme = async () => { const findTheme = async () => {
const theme = await AsyncStorage.getItem('theme'); const res = await db.from("settings").select().eq({id: 'theme'})
let theme = 'auto'
if (!res.error){
if (res.data.length > 0){
theme = res.data[0].value
}else{
const res = await db.from('settings').insert({id: 'theme', value: 'auto'})
console.log(res)
}
}
if(theme === 'dark') { if(theme === 'dark') {
return dark; return dark;
} else if(theme === 'light') { } else if(theme === 'light') {
@ -35,7 +44,13 @@ const findTheme = async () => {
} }
const findThemeMode = async () => { const findThemeMode = async () => {
const theme = await AsyncStorage.getItem('theme'); const res = await db.from("settings").select().eq({id:'theme'})
let theme = 'auto'
if (!res.error){
if (res.data.length > 0){
theme = res.data[0].value
}
}
if (theme){ if (theme){
return theme; return theme;
} else { } else {
@ -55,7 +70,6 @@ export default function App() {
const [others, setOthers] = useState([]); const [others, setOthers] = useState([]);
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
const theme = await findTheme(); const theme = await findTheme();
@ -97,22 +111,22 @@ export default function App() {
case 'dark': case 'dark':
setThemeMode('dark'); setThemeMode('dark');
setTheme(dark); setTheme(dark);
await AsyncStorage.setItem('theme', 'dark'); await db.from("settings").update({value: 'dark'}).eq({id: 'theme'})
break; break;
case 'light': case 'light':
setThemeMode('light'); setThemeMode('light');
setTheme(light); setTheme(light);
await AsyncStorage.setItem('theme', 'light'); await db.from('settings').update({value: 'light'}).eq({id: 'theme'})
break; break;
case 'solorizedDark': case 'solorizedDark':
setThemeMode('solorizedDark'); setThemeMode('solorizedDark');
setTheme(solorizedDark); setTheme(solorizedDark);
await AsyncStorage.setItem('theme', 'solorizedDark'); await db.from('settings').update({value: 'solorizedDark'}).eq({id: 'theme'})
break; break;
case 'oled': case 'oled':
setThemeMode('oled'); setThemeMode('oled');
setTheme(oled); setTheme(oled);
await AsyncStorage.setItem('theme', 'oled'); await db.from('settings').update({value: 'oled'}).eq({id: 'theme'})
break; break;
default: default:
setThemeMode('auto'); setThemeMode('auto');
@ -122,7 +136,7 @@ export default function App() {
} else { } else {
setTheme(light); setTheme(light);
} }
await AsyncStorage.setItem('theme', "auto"); await db.from('settings').update({id: 'theme', value: 'auto'}).eq({id: 'theme'})
break; break;
} }
} }

View File

@ -1,3 +1,5 @@
# Tali # Tali
React Native app to keep track of movies, tv shows and other interesting stuff you want to watch or do. Gone are the days of using an unorganized note app to keep track of what you want to or already have watched. React Native app to keep track of movies, tv shows and other interesting stuff you want to watch or do. Gone are the days of using an unorganized note app to keep track of what you want to or already have watched.
![tali-grid-preview](https://github.com/MoistOverflow/Tali/assets/96554264/91330631-26fb-47f3-84e6-958064a0470d)

View File

@ -9,7 +9,7 @@
"splash": { "splash": {
"image": "./assets/splash.png", "image": "./assets/splash.png",
"resizeMode": "contain", "resizeMode": "contain",
"backgroundColor": "#ffffff" "backgroundColor": "#000000"
}, },
"assetBundlePatterns": [ "assetBundlePatterns": [
"**/*" "**/*"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,5 +1,5 @@
import nasa from './nasa'; import nasa from './nasa';
import { MovieSchema, ShowSchema, TestTableShema, OtherSchema, CategorySchema} from './schemas'; import { MovieSchema, ShowSchema, TestTableShema, OtherSchema, CategorySchema, SettingSchema} from './schemas';
const tableSchemas = { const tableSchemas = {
@ -7,7 +7,7 @@ const tableSchemas = {
shows: ShowSchema, shows: ShowSchema,
others: OtherSchema, others: OtherSchema,
categories: CategorySchema, categories: CategorySchema,
test: TestTableShema, settings: SettingSchema ,
} }

View File

@ -55,6 +55,15 @@ export default class nasa{
let table:any = await AsyncStorage.getItem(this.#tableName); let table:any = await AsyncStorage.getItem(this.#tableName);
if(table){ if(table){
table = JSON.parse(table); table = JSON.parse(table);
console.log(newData)
if ('id' in newData){
table.forEach((s:any)=>{
if(s.id === newData.id){
this.error = 'Id already exists';
return this
}
});
}else{
let maxId = 0; let maxId = 0;
table.forEach((s:any)=>{ table.forEach((s:any)=>{
if(s.id > maxId){ if(s.id > maxId){
@ -62,6 +71,7 @@ export default class nasa{
} }
}); });
newData.id = maxId + 1; newData.id = maxId + 1;
}
const {data, error} = await this.#tableSchemas[this.#tableName].safeParse(newData); const {data, error} = await this.#tableSchemas[this.#tableName].safeParse(newData);
if(error){ if(error){
this.error = error.message; this.error = error.message;
@ -72,7 +82,9 @@ export default class nasa{
this.data = data this.data = data
return this; return this;
}else{ }else{
if (!('id' in newData)){
newData.id = 1; newData.id = 1;
}
const {data, error} = await this.#tableSchemas[this.#tableName].safeParse(newData); const {data, error} = await this.#tableSchemas[this.#tableName].safeParse(newData);
if(error){ if(error){
this.error = error.message; this.error = error.message;

View File

@ -89,3 +89,9 @@ export const TestTableShema = z.object({
test: z.string(), test: z.string(),
}).strict(); }).strict();
export type TestTable = z.infer<typeof TestTableShema>; export type TestTable = z.infer<typeof TestTableShema>;
export const SettingSchema = z.object({
id: z.string(),
value: z.string().or(z.boolean().or(z.number()))
})
export type SettingsTable = z.infer<typeof SettingSchema>

View File

@ -244,6 +244,12 @@ const style = (theme:any) => {
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
}, },
delete: {
color: 'red',
textAlign: 'center',
marginTop: 10,
},
}); });
} }
@ -457,8 +463,8 @@ function EditMovieModal({editMovie, setEdditMovie, update, theme, remove}:any){
value={editMovie.notes} value={editMovie.notes}
/> />
</View> </View>
<View style={{...st.row, width: '90%', marginLeft: 20, justifyContent: "flex-start"}}> <View style={{...st.row, width: '90%', marginLeft: 20, justifyContent: "center"}}>
<Button title="delete" onPress={()=>remove(editMovie.id)} theme={theme} style={{backgroundColor: theme.danger, paddingHorizontal: 25, margin: 0}}/> <Text style={st.delete} onLongPress={()=>remove(editMovie.id)}>long press to delete</Text>
</View> </View>
</View> </View>
</View> </View>

View File

@ -266,6 +266,11 @@ const style = (theme:any) => {
paddingHorizontal: 10, paddingHorizontal: 10,
padding: 5, padding: 5,
}, },
delete: {
color: 'red',
textAlign: 'center',
marginTop: 10,
},
}); });
} }
@ -520,8 +525,8 @@ function EditshowModal({editOther, setEditOther, update, theme, remove, selCat}:
value={editOther.notes} value={editOther.notes}
/> />
</View> </View>
<View style={{...st.row, width: '90%', marginLeft: 20, justifyContent: "flex-start"}}> <View style={{...st.row, width: '90%', marginLeft: 20, justifyContent: "center"}}>
<Button title="delete" onPress={()=>remove(editOther.id)} theme={theme} style={{backgroundColor: theme.danger, paddingHorizontal: 25, margin: 0,}}/> <Text style={st.delete} onLongPress={()=>remove(editor.id)}>long press to delete</Text>
</View> </View>
</View> </View>
</View> </View>

View File

@ -58,10 +58,11 @@ export default function OtherCat({theme, otherCategories, setOtherCategories, se
} }
const handleDelete = async () => { const handleDelete = async () => {
const res = await db.from('categories').delete().eq({id: newCat.id}); let res = await db.from('categories').delete().eq({id: newCat.id});
if (res.data) { if (res.data) {
setOtherCategories([...otherCategories.filter((c:any) => c.id !== newCat.id)]) setOtherCategories([...otherCategories.filter((c:any) => c.id !== newCat.id)])
} }
res = await db.from('others').delete().eq({category: newCat.id})
setModalVisible(false); setModalVisible(false);
setNewCat({title: '', showEpisodes: false}); setNewCat({title: '', showEpisodes: false});
setEditPop(false); setEditPop(false);

View File

@ -27,13 +27,10 @@ export default function Settings({theme, changeTheme, themeMode, clearAll, resyn
const handleExport = async () => { const handleExport = async () => {
const dataToExport = await db.fileExport() const dataToExport = await db.fileExport()
const data = JSON.stringify(dataToExport); const data = JSON.stringify(dataToExport);
// export dataToExport in json format to a file using react-native-fs
if (Platform.OS === 'android') { if (Platform.OS === 'android') {
const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync(); const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync();
if (permissions.granted) { if (permissions.granted) {
// Gets SAF URI from response
const uri = permissions.directoryUri; const uri = permissions.directoryUri;
// Writes file to SAF URI
await StorageAccessFramework.createFileAsync(uri, 'tali', 'application/json').then(async (fileUri) => { await StorageAccessFramework.createFileAsync(uri, 'tali', 'application/json').then(async (fileUri) => {
await StorageAccessFramework.writeAsStringAsync(fileUri, data, { encoding: FileSystem.EncodingType.UTF8 }).catch((err) => console.log(err)) await StorageAccessFramework.writeAsStringAsync(fileUri, data, { encoding: FileSystem.EncodingType.UTF8 }).catch((err) => console.log(err))
}) })
@ -104,8 +101,8 @@ export default function Settings({theme, changeTheme, themeMode, clearAll, resyn
/> />
</View> </View>
<View style={{...st.row, zIndex:0}}> <View style={{...st.row, zIndex:0}}>
<Button theme={theme} title="Export Data" onPress={handleExport} style={{padding:30, flex:1}}/> <Button theme={theme} title="Export" onPress={handleExport} style={{padding:30, flex:1}}/>
<Button theme={theme} title="Import Data" onPress={handleImport} style={{padding:30, flex:1}}/> <Button theme={theme} title="Import" onPress={handleImport} style={{padding:30, flex:1}}/>
</View> </View>
<View style={{...st.row, zIndex:0}}> <View style={{...st.row, zIndex:0}}>
<Button theme={theme} title="Delete All Data" onPress={() => setDeleteAllModal(true)} style={{width:'100%'}}/> <Button theme={theme} title="Delete All Data" onPress={() => setDeleteAllModal(true)} style={{width:'100%'}}/>

View File

@ -265,6 +265,11 @@ const style = (theme:any) => {
paddingHorizontal: 10, paddingHorizontal: 10,
padding: 5, padding: 5,
}, },
delete: {
color: 'red',
textAlign: 'center',
marginTop: 10,
},
}); });
} }
@ -517,8 +522,8 @@ function EditshowModal({editShow, setEditShow, update, theme, remove}:any){
value={editShow.notes} value={editShow.notes}
/> />
</View> </View>
<View style={{...st.row, width: '90%', marginLeft: 20, justifyContent: "flex-start"}}> <View style={{...st.row, width: '90%', marginLeft: 20, justifyContent: "center"}}>
<Button title="delete" onPress={()=>remove(editShow.id)} theme={theme} style={{backgroundColor: theme.danger, paddingHorizontal: 25, margin: 0,}}/> <Text style={st.delete} onLongPress={()=>remove(editShow.id)}>long press to delete</Text>
</View> </View>
</View> </View>
</View> </View>