aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2024-09-28 13:46:22 +0530
committerAkshay Nair <phenax5@gmail.com>2024-09-29 16:16:39 +0530
commita1143f3696a0b272018f7eea43ee23a674c618e1 (patch)
tree2289e6a1fbf47d339cb41849f9554d403bd837cc /src
parent5d456899ea444301870e1d3c721d139c9251c531 (diff)
downloaddaft-launcher-a1143f3696a0b272018f7eea43ee23a674c618e1.tar.gz
daft-launcher-a1143f3696a0b272018f7eea43ee23a674c618e1.zip
Add context menu for apps (fav,settings,uninstall)
Diffstat (limited to 'src')
-rw-r--r--src/View.tsx29
-rw-r--r--src/components/AppMenu.tsx79
-rw-r--r--src/components/Clock.tsx4
-rw-r--r--src/components/Favorites.tsx49
-rw-r--r--src/hooks/useFavorites.ts14
-rw-r--r--src/screens/AppList.tsx22
-rw-r--r--src/screens/Home.tsx7
7 files changed, 166 insertions, 38 deletions
diff --git a/src/View.tsx b/src/View.tsx
new file mode 100644
index 0000000..c5084f2
--- /dev/null
+++ b/src/View.tsx
@@ -0,0 +1,29 @@
+import React, {useState} from 'react';
+import {InstalledApps} from 'react-native-launcher-kit';
+import Swiper from 'react-native-swiper';
+import {AppList} from './screens/AppList';
+import {Home} from './screens/Home';
+
+export const View: React.FC = () => {
+ const [apps, _setApps] = useState(() => InstalledApps.getSortedApps());
+ const [screenIndex, setScreenIndex] = useState(0);
+
+ // const refreshApps = () => setApps(InstalledApps.getSortedApps());
+
+ // useEffect(() => {
+ // refreshApps();
+ // }, [screenIndex]);
+
+ return (
+ <Swiper
+ horizontal
+ autoplay={false}
+ loop={false}
+ dot={<></>}
+ activeDot={<></>}
+ onIndexChanged={setScreenIndex}>
+ <Home apps={apps} active={screenIndex === 0} />
+ <AppList apps={apps} active={screenIndex === 1} />
+ </Swiper>
+ );
+};
diff --git a/src/components/AppMenu.tsx b/src/components/AppMenu.tsx
new file mode 100644
index 0000000..ec0d684
--- /dev/null
+++ b/src/components/AppMenu.tsx
@@ -0,0 +1,79 @@
+import {Text, View, Modal, TouchableOpacity, Pressable} from 'react-native';
+import {AppDetail} from 'react-native-launcher-kit/typescript/Interfaces/InstalledApps';
+import {useFavorites} from '../hooks/useFavorites';
+import React, {useState} from 'react';
+import IntentLauncher from '@angelkrak/react-native-intent-launcher';
+
+export const AppMenu: React.FC<React.PropsWithChildren<{app: AppDetail}>> = ({
+ app,
+ children,
+}) => {
+ const [isOpen, setIsOpen] = useState(false);
+ const {addToFavorites, isFavorite, removeFromFavorites} = useFavorites();
+
+ const menuPress = (fn: () => Promise<void> | void) => async () => {
+ await fn();
+ setIsOpen(false);
+ };
+
+ const menuItems = [
+ isFavorite(app.packageName)
+ ? {
+ label: 'Remove from favorites',
+ onPress: menuPress(() => removeFromFavorites(app.packageName)),
+ }
+ : {
+ label: 'Add to favorites',
+ onPress: menuPress(() => addToFavorites(app.packageName)),
+ },
+ {
+ label: 'App info',
+ onPress: menuPress(() =>
+ IntentLauncher.startActivity({
+ action: 'android.settings.APPLICATION_DETAILS_SETTINGS',
+ data: 'package:' + app.packageName,
+ }),
+ ),
+ },
+ {
+ label: 'Uninstall',
+ onPress: menuPress(() =>
+ IntentLauncher.startActivity({
+ action: 'android.intent.action.DELETE',
+ data: 'package:' + app.packageName,
+ }),
+ ),
+ },
+ ];
+
+ return (
+ <>
+ <TouchableOpacity onLongPress={() => setIsOpen(true)}>
+ {children}
+ </TouchableOpacity>
+
+ <Modal
+ visible={isOpen}
+ transparent={true}
+ animationType="none"
+ onRequestClose={() => setIsOpen(false)}>
+ <TouchableOpacity className="flex-1" onPress={() => setIsOpen(false)}>
+ <View className="flex justify-center items-center h-full">
+ <View className="shadow-lg bg-gray-900 w-2/3">
+ {menuItems.map((menuItem) => (
+ <Pressable
+ key={menuItem.label}
+ onPress={menuItem.onPress}
+ className="py-3 px-4 border-b border-gray-800 last:border-b-0">
+ <Text className="text-lg text-gray-300">
+ {menuItem.label}
+ </Text>
+ </Pressable>
+ ))}
+ </View>
+ </View>
+ </TouchableOpacity>
+ </Modal>
+ </>
+ );
+};
diff --git a/src/components/Clock.tsx b/src/components/Clock.tsx
index 113201f..619a31b 100644
--- a/src/components/Clock.tsx
+++ b/src/components/Clock.tsx
@@ -14,7 +14,7 @@ export const Clock: React.FC = () => {
const formatter = new Intl.DateTimeFormat('en', {
hour: 'numeric',
minute: 'numeric',
- second: 'numeric',
+ // second: 'numeric',
});
return formatter.format(date);
}, [date]);
@@ -30,7 +30,7 @@ export const Clock: React.FC = () => {
return (
<View className="p-6">
- <Text className="text-3xl font-bold">{timeText}</Text>
+ <Text className="text-4xl font-bold">{timeText}</Text>
<Text className="text-lg">{dateText}</Text>
</View>
);
diff --git a/src/components/Favorites.tsx b/src/components/Favorites.tsx
index 85ab3c2..c2adae7 100644
--- a/src/components/Favorites.tsx
+++ b/src/components/Favorites.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useMemo} from 'react';
+import React, {useCallback, useEffect, useMemo} from 'react';
import {Text, TouchableOpacity, View} from 'react-native';
import {AppDetail} from 'react-native-launcher-kit/typescript/Interfaces/InstalledApps';
import {useFavorites} from '../hooks/useFavorites';
@@ -8,9 +8,13 @@ import DraggableFlatList, {
ShadowDecorator,
} from 'react-native-draggable-flatlist';
import Icon from 'react-native-vector-icons/MaterialIcons';
+import {AppMenu} from './AppMenu';
-export const Favorites: React.FC<{apps: AppDetail[]}> = ({apps}) => {
- const {favoriteAppNames, setFavorites} = useFavorites();
+export const Favorites: React.FC<{apps: AppDetail[]; active: boolean}> = ({
+ apps,
+ active,
+}) => {
+ const {favoriteAppNames, setFavorites, refreshFavorites} = useFavorites();
const appByName = useMemo(
() => Object.fromEntries(apps.map((app) => [app.packageName, app])),
@@ -29,8 +33,13 @@ export const Favorites: React.FC<{apps: AppDetail[]}> = ({apps}) => {
[setFavorites],
);
+ useEffect(() => {
+ if (!active) return;
+ refreshFavorites();
+ }, [active, refreshFavorites]);
+
return (
- <View className="px-4">
+ <View className="px-4 py-1">
<DraggableFlatList
data={favoriteApps}
onDragEnd={onDragEnd}
@@ -38,24 +47,26 @@ export const Favorites: React.FC<{apps: AppDetail[]}> = ({apps}) => {
renderItem={({item: app, drag, isActive}) => (
<ShadowDecorator>
<OpacityDecorator>
- <View
- className={`py-2 px-2 flex-row w-full ${
- isActive ? 'bg-gray-200 opacity-60' : ''
- }`}>
- <Text className="text-lg flex-1">{app.label}</Text>
- <TouchableOpacity
- onLongPress={drag}
- disabled={isActive}
- delayLongPress={500}>
- <View className={'py-1'}>
- <Icon name="drag-indicator" size={21} color="#aaa" />
- </View>
- </TouchableOpacity>
- </View>
+ <AppMenu app={app}>
+ <View
+ className={`py-3 px-2 flex-row w-full ${
+ isActive ? 'bg-gray-950 opacity-60' : ''
+ }`}>
+ <Text className="text-lg flex-1">{app.label}</Text>
+ <TouchableOpacity
+ onLongPress={drag}
+ disabled={isActive}
+ delayLongPress={500}>
+ <View className="py-1">
+ <Icon name="drag-indicator" size={21} color="#444" />
+ </View>
+ </TouchableOpacity>
+ </View>
+ </AppMenu>
</OpacityDecorator>
</ShadowDecorator>
)}
- renderPlaceholder={() => <View className="flex-1 bg-gray-200" />}
+ renderPlaceholder={() => <View className="flex-1 bg-gray-950" />}
/>
</View>
);
diff --git a/src/hooks/useFavorites.ts b/src/hooks/useFavorites.ts
index 619817c..46b6e77 100644
--- a/src/hooks/useFavorites.ts
+++ b/src/hooks/useFavorites.ts
@@ -24,24 +24,34 @@ export const useFavorites = () => {
const setFavorites = useStableCallback(async (names: string[]) => {
const newNames = [...new Set(names)];
- setFavoriteAppNames(newNames);
await favoritesStorage.setItem(JSON.stringify(newNames));
+ refreshFavorites();
});
const addToFavorites = useStableCallback(async (packageName: string) => {
const names = await getFavoriteAppNames();
setFavorites([...names, packageName]);
});
+ const removeFromFavorites = useStableCallback(async (packageName: string) => {
+ const names = await getFavoriteAppNames();
+ setFavorites(names.filter((name) => name !== packageName));
+ });
+
+ const isFavorite = useStableCallback((packageName: string) =>
+ favoriteAppNames.includes(packageName),
+ );
useEffect(() => {
refreshFavorites();
}, [refreshFavorites]);
return {
+ addToFavorites,
favoriteAppNames,
getFavoriteAppNames,
- addToFavorites,
+ isFavorite,
refreshFavorites,
+ removeFromFavorites,
setFavorites,
};
};
diff --git a/src/screens/AppList.tsx b/src/screens/AppList.tsx
index 81c8f4f..e6b3e6e 100644
--- a/src/screens/AppList.tsx
+++ b/src/screens/AppList.tsx
@@ -2,16 +2,13 @@ import {matchSorter} from 'match-sorter';
import React, {useEffect, useMemo, useRef, useState} from 'react';
import {ScrollView, Text, TextInput, View} from 'react-native';
import {AppDetail} from 'react-native-launcher-kit/typescript/Interfaces/InstalledApps';
-import {useFavorites} from '../hooks/useFavorites';
-import {TouchableOpacity} from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialIcons';
+import {AppMenu} from '../components/AppMenu';
-export const AppList: React.FC<{apps: AppDetail[]; isActive: boolean}> = ({
+export const AppList: React.FC<{apps: AppDetail[]; active: boolean}> = ({
apps,
- isActive,
+ active,
}) => {
- const {addToFavorites} = useFavorites();
-
const textInputRef = useRef<TextInput>(null);
const [searchText, setSearchText] = useState('');
@@ -24,8 +21,8 @@ export const AppList: React.FC<{apps: AppDetail[]; isActive: boolean}> = ({
// Autofocus
useEffect(() => {
if (!textInputRef.current) return;
- if (isActive) TextInput.State.focusTextInput(textInputRef.current);
- }, [isActive]);
+ if (active) TextInput.State.focusTextInput(textInputRef.current);
+ }, [active]);
return (
<View>
@@ -44,15 +41,14 @@ export const AppList: React.FC<{apps: AppDetail[]; isActive: boolean}> = ({
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View className="flex-1">
{filteredApps.map((app, index) => (
- <View className="mt-4 px-4" key={app.packageName + index}>
- <TouchableOpacity
- onLongPress={() => addToFavorites(app.packageName)}>
+ <AppMenu app={app} key={app.packageName + index}>
+ <View className="mt-4 px-4">
<Text className="text-md font-bold dark:text-white">
{app.label}
</Text>
<Text className="text-xs">{app.packageName}</Text>
- </TouchableOpacity>
- </View>
+ </View>
+ </AppMenu>
))}
</View>
</ScrollView>
diff --git a/src/screens/Home.tsx b/src/screens/Home.tsx
index 00a4b1f..7bd1a3f 100644
--- a/src/screens/Home.tsx
+++ b/src/screens/Home.tsx
@@ -4,11 +4,14 @@ import {Clock} from '../components/Clock';
import {AppDetail} from 'react-native-launcher-kit/typescript/Interfaces/InstalledApps';
import {Favorites} from '../components/Favorites';
-export const Home: React.FC<{apps: AppDetail[]}> = ({apps}) => {
+export const Home: React.FC<{apps: AppDetail[]; active: boolean}> = ({
+ apps,
+ active,
+}) => {
return (
<View>
<Clock />
- <Favorites apps={apps} />
+ <Favorites apps={apps} active={active} />
</View>
);
};