Skip to content

Commit

Permalink
Merge pull request Memmy-App#12 from gkasdorf/development
Browse files Browse the repository at this point in the history
0.0.1 (9)
  • Loading branch information
gkasdorf authored Jun 14, 2023
2 parents 217695e + f76dd66 commit bf56952
Show file tree
Hide file tree
Showing 27 changed files with 1,030 additions and 624 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ web-build/
.DS_Store

*.tar.gz
*.ipa
*.ipa
*.apk
*.aab
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# memmy - An iOS client for Lemmy
# memmy - An iOS and Android client for Lemmy

An Apollo-inspired iOS client for using [Lemmy](https://github.com/LemmyNet/lemmy), a federated link aggregator.
An Apollo-inspired iOS and Android client for using [Lemmy](https://github.com/LemmyNet/lemmy), a federated link aggregator.

## Work in Progress
This is a work in progress and is not in a function state - yet. I intend to release builds on TestFlight starting in
Expand All @@ -14,7 +14,12 @@ to create your own builds.
```shell
git clone https://github.com/gkasdorf/memmy.git
cd memmy
eas build -p ios --profile preview --local --output memmy-build.ipa

# IOS
eas build -p ios --profile preview --local --output memmy-build.ipa

# Android
eas build -p android --profile preview --local --output memmy-build.apk
```

Install the application through Xcode devices or however else you wish to install.
Expand All @@ -28,11 +33,6 @@ there are already a few projects out there that are using Swift to create their
have a codebase where those who may not have a good grasp of native mobile app development to have a chance to contribute,
such as those who already have a good grasp of React.

#### Easily portable to Android
Although I am not currently targeting Android, creating Android builds from this codebase will be certainly possible,
with minor changes. If you are interested in doing this but don't know how to go about it, reach out and I will point
you in the right direction.

#### Compatible with already existing libraries
Especially since Lemmy is an ongoing project that will certainly evolve over time, we can easily use the official
[lemmy-js-client](https://github.com/LemmyNet/lemmy-js-client) library to make our API calls. If changes to the API are
Expand Down
13 changes: 9 additions & 4 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,24 @@
}
},
"ios": {
"bundleIdentifier": "com.gkasdorf.memmyapp",
"supportsTablet": false,
"buildNumber": "3"
"bundleIdentifier": "com.gkasdorf.memmyapp",
"buildNumber": "9"
},
"plugins": [
[
"expo-build-properties",
{
"ios": {
"flipper": true
"flipper": true,
"deploymentTarget": "15.0"
}
}
]
]
],
"android": {
"package": "com.gkasdorf.memmyapp",
"versionCode": 2
}
}
}
13 changes: 8 additions & 5 deletions app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import React, {useEffect} from "react";
import {Settings} from "react-native";
import {SplashScreen, useRootNavigationState, useRouter} from "expo-router";
import ILemmyServer from "../lemmy/types/ILemmyServer";
import {getServers} from "../helpers/SettingsHelper";

const IndexScreen = () => {
const servers = Settings.get("servers") as ILemmyServer[];

const router = useRouter();
const navState = useRootNavigationState();

Expand All @@ -14,14 +11,20 @@ const IndexScreen = () => {
return;
}

load().then();
}, [navState?.key]);

const load = async () => {
const servers = await getServers();

if(!servers || servers.length < 1) {
router.replace("/onboarding");
return;
} else {
router.replace("/tabs/feeds");
return;
}
}, [navState?.key]);
};

return <SplashScreen />;
};
Expand Down
8 changes: 5 additions & 3 deletions app/onboarding/addAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import ILemmyServer from "../../lemmy/types/ILemmyServer";
import {KeyboardAwareScrollView} from "react-native-keyboard-aware-scroll-view";
import {useRouter} from "expo-router";
import {initialize, lemmyAuthToken} from "../../lemmy/LemmyInstance";
import LoadingModal from "../../ui/LoadingModal";
import {addServer} from "../../helpers/SettingsHelper";

const AddAccountScreen = () => {
const [form, setForm] = useState<ILemmyServer>({
Expand Down Expand Up @@ -58,16 +60,16 @@ const AddAccountScreen = () => {

server.auth = lemmyAuthToken;

Settings.set({
servers: [server]
});
await addServer(server);

setLoading(false);
router.replace("/tabs/feeds");
};

return (
<KeyboardAwareScrollView>
<LoadingModal loading={loading} />

<VStack pt={10} mb={5} space={"md"} justifyContent={"center"}>
<Text fontSize={32} textAlign={"center"}>
Existing Account
Expand Down
5 changes: 2 additions & 3 deletions app/onboarding/createAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {KeyboardAwareScrollView} from "react-native-keyboard-aware-scroll-view";
import CTextInput from "../../ui/CTextInput";
import {LemmyHttp} from "lemmy-js-client";
import LoadingModal from "../../ui/LoadingModal";
import {addServer} from "../../helpers/SettingsHelper";

interface RegisterForm {
server: string,
Expand Down Expand Up @@ -125,9 +126,7 @@ const CreateAccountScreen = () => {

server.auth = lemmyAuthToken;

Settings.set({
servers: [server]
});
await addServer(server);

setLoading(false);
router.replace("/tabs/feeds");
Expand Down
2 changes: 1 addition & 1 deletion app/tabs/feeds/[communityId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const FeedsCommunityScreen = () => {
}
};

return <FeedView posts={posts} load={load} loading={loading} setSort={setSort} />;
return <FeedView posts={posts} load={load} loading={loading} setSort={setSort} communityTitle={true} />;
};

export default FeedsCommunityScreen;
3 changes: 2 additions & 1 deletion app/tabs/feeds/commentModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ const styles = StyleSheet.create({
alignSelf: "stretch",
padding: 10,
paddingTop: 15,
height: 300
height: 300,
fontSize: 16
}
});

Expand Down
13 changes: 7 additions & 6 deletions app/tabs/feeds/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, {useEffect, useState} from "react";
import {Settings} from "react-native";
import ILemmyServer from "../../../lemmy/types/ILemmyServer";
import {initialize, lemmyAuthToken, lemmyInstance} from "../../../lemmy/LemmyInstance";
import FeedView from "../../../ui/Feed/FeedView";
import {useAppDispatch, useAppSelector} from "../../../store";
import {getAllCommunities, getSubscribedCommunities} from "../../../slices/communities/communitiesActions";
import {PostView, SortType} from "lemmy-js-client";
import {clearUpdateVote, selectFeed} from "../../../slices/feed/feedSlice";
import {getServers} from "../../../helpers/SettingsHelper";

const FeedsIndexScreen = () => {
const dispatch = useAppDispatch();
Expand All @@ -15,7 +14,7 @@ const FeedsIndexScreen = () => {
const [loading, setLoading] = useState(false);
const [sort, setSort] = useState<SortType>("Hot");

const {updateVote} = useAppSelector(selectFeed);
const {updateVote, listingType} = useAppSelector(selectFeed);

useEffect(() => {
if(updateVote) {
Expand All @@ -32,13 +31,14 @@ const FeedsIndexScreen = () => {

useEffect(() => {
load(true).then();
}, [sort]);
}, [sort, listingType]);

const load = async (refresh = false) => {
setLoading(true);

try {
await initialize((Settings.get("servers") as ILemmyServer[])?.[0]);
const servers = await getServers();
await initialize(servers[0]);
} catch(e) {
console.log("Error: ", e);
setPosts(null);
Expand All @@ -51,7 +51,8 @@ const FeedsIndexScreen = () => {
auth: lemmyAuthToken,
limit: 50,
page: !posts ? 1 : (posts.length / 50) + 1,
sort: sort
sort: sort,
type_: listingType,
});

if(!posts || refresh) {
Expand Down
15 changes: 6 additions & 9 deletions app/tabs/feeds/post.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {useEffect, useState} from "react";
import {Stack, useRouter} from "expo-router";
import {Link, Stack, useRouter} from "expo-router";
import {lemmyAuthToken, lemmyInstance} from "../../../lemmy/LemmyInstance";
import LoadingView from "../../../ui/LoadingView";
import {ArrowDownIcon, ArrowUpIcon, Center, Divider, HStack, Icon, IconButton, Spinner, Text, View,} from "native-base";
Expand Down Expand Up @@ -80,7 +80,7 @@ const PostScreen = () => {
};

const onVotePress = async (value: -1 | 0 | 1) => {
if(value === post.my_vote) value = 0;
if(value === post.my_vote && value !== 0) value = 0;

const oldValue = post.my_vote;

Expand Down Expand Up @@ -131,13 +131,9 @@ const PostScreen = () => {
}}
/>
<Text fontSize={"2xl"}>{post.post.name}</Text>
<ContentView post={post} />
<HStack mt={2}>
<Text>in </Text>
<Text fontWeight={"bold"}>{post.community.name} </Text>
<Text>by </Text>
<Text fontWeight={"bold"}>{post.creator.name}</Text>
</HStack>

<ContentView post={post} alwaysShowBody={true} />

<HStack mt={2} space={3} alignItems={"center"}>
<HStack space={1} alignItems={"center"}>
{
Expand Down Expand Up @@ -192,6 +188,7 @@ const PostScreen = () => {
<IconButton icon={<Icon as={Ionicons} name={"arrow-undo-outline"} />} onPress={onCommentPress} />
<IconButton icon={<Icon as={Ionicons} name={"share-outline"} />} />
</HStack>
<Divider />
</View>
);

Expand Down
23 changes: 12 additions & 11 deletions app/tabs/settings/editAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Cell, Section, TableView} from "react-native-tableview-simple";
import ILemmyServer from "../../../lemmy/types/ILemmyServer";
import {Stack, useRouter, useSearchParams} from "expo-router";
import {initialize, lemmyAuthToken} from "../../../lemmy/LemmyInstance";
import {getServers, setServers} from "../../../helpers/SettingsHelper";

const EditAccountScreen = () => {
const [form, setForm] = useState<ILemmyServer>({
Expand All @@ -22,11 +23,15 @@ const EditAccountScreen = () => {

useEffect(() => {
if(serverIndex) {
const servers = Settings.get("servers");
setForm(servers[Number(serverIndex)] as ILemmyServer);
load().then();
}
}, []);

const load = async () => {
const servers = await getServers();
setForm(servers[Number(serverIndex)]);
};

const onFormChange = (name: string, value: string) => {
setForm({
...form,
Expand All @@ -53,7 +58,7 @@ const EditAccountScreen = () => {
return;
}

const servers = Settings.get("servers") as ILemmyServer[] ?? [];
const servers = await getServers() ?? [];
const serverIndex = servers.findIndex((x) => (x.server.toLowerCase() === form.server.toLowerCase() && x.username.toLowerCase() === form.username.toLowerCase()));

if(serverIndex > -1) {
Expand All @@ -68,22 +73,18 @@ const EditAccountScreen = () => {
});
}

Settings.set({
servers
});
await setServers(servers);

router.back();
};

const onDeletePress = () => {
const servers = Settings.get("servers") as ILemmyServer[];
const onDeletePress = async () => {
const servers = await getServers();
const serverIndex = servers.findIndex((x) => (x.server.toLowerCase() === form.server.toLowerCase() && x.username.toLowerCase() === form.username.toLowerCase()));

delete servers[serverIndex];

Settings.set({
servers
});
await setServers(servers);

router.back();
};
Expand Down
18 changes: 14 additions & 4 deletions app/tabs/settings/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
import React, {useCallback, useState} from "react";
import {VStack} from "native-base";
import {Settings, StyleSheet, Switch} from "react-native";
import {StyleSheet, Switch} from "react-native";
import {Cell, Section, TableView} from "react-native-tableview-simple";
import {useFocusEffect, useRouter} from "expo-router";
import ILemmyServer from "../../../lemmy/types/ILemmyServer";
import {getBuildNumber, getVersion} from "react-native-device-info";
import {getServers} from "../../../helpers/SettingsHelper";
import LoadingView from "../../../ui/LoadingView";

const SettingsIndexScreen = () => {
const [server, setServer] = useState(Settings.get("servers")[0] as ILemmyServer);
const [server, setServer] = useState(null);

const router = useRouter();

useFocusEffect(useCallback(() => {
setServer(Settings.get("servers")[0] as ILemmyServer);
load().then();
}, []));

const load = async () => {
const servers = await getServers();
setServer(servers[0]);
};

if(!server) {
return <LoadingView />;
}

return (
<VStack>
<TableView style={styles.table}>
Expand Down
20 changes: 20 additions & 0 deletions helpers/SettingsHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import ILemmyServer from "../lemmy/types/ILemmyServer";
import AsyncStorage from "@react-native-async-storage/async-storage";

export const getServers = async (): Promise<ILemmyServer[] | null> => {
const serversStr = await AsyncStorage.getItem("@servers");

if(!serversStr) return null;

return JSON.parse(serversStr) as ILemmyServer[];
};

export const addServer = async (server: ILemmyServer) => {
const servers = await getServers() ?? [];
servers.push(server);
await AsyncStorage.setItem("@servers", JSON.stringify(servers));
};

export const setServers = async(servers: ILemmyServer[]) => {
await AsyncStorage.setItem("@servers", JSON.stringify(servers));
};
Loading

0 comments on commit bf56952

Please sign in to comment.