Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ node_modules/

# Expo
.expo/
.idea/
dist/
web-build/
expo-env.d.ts
Expand Down
12 changes: 0 additions & 12 deletions .idea/fronted.iml

This file was deleted.

8 changes: 0 additions & 8 deletions .idea/modules.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

49 changes: 27 additions & 22 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion app/(main)/teams.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const TeamsScreen = () => {

useEffect(() => {
if (teams.length < currentPage * perPage && hasMoreTeamsLocal) {
console.log("wywołuje");
getData();
}
}, [currentPage]);
Expand Down
10 changes: 8 additions & 2 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { store } from "@/core/store";

Check failure on line 1 in app/_layout.tsx

View workflow job for this annotation

GitHub Actions / quality

organizeImports

Import statements differs from the output

Check failure on line 1 in app/_layout.tsx

View workflow job for this annotation

GitHub Actions / quality

format

File content differs from formatting output

Check failure on line 1 in app/_layout.tsx

View workflow job for this annotation

GitHub Actions / quality

organizeImports

Import statements differs from the output

Check failure on line 1 in app/_layout.tsx

View workflow job for this annotation

GitHub Actions / quality

format

File content differs from formatting output
import { useColorScheme } from "@/hooks/useColorScheme";
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
import { DarkTheme, DefaultTheme, ThemeProvider } from "@react-navigation/native";
Expand All @@ -7,13 +7,19 @@
import { GestureHandlerRootView } from "react-native-gesture-handler";
import "react-native-reanimated";
import { Provider } from "react-redux";
import React from 'react';

import { EchoListener } from "@/components/EchoListener"; // nowy komponent (poniżej)

export default function RootLayout() {
const colorScheme = useColorScheme();

return (
<Provider store={store}>
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<GestureHandlerRootView>
<GestureHandlerRootView style={{ flex: 1 }}>
<BottomSheetModalProvider>
<EchoListener />
<Stack>
<Stack.Screen name="(auth)/index" options={{ headerShown: false }} />
<Stack.Screen name="(main)" options={{ headerShown: false }} />
Expand All @@ -25,4 +31,4 @@
</ThemeProvider>
</Provider>
);
}
}
115 changes: 115 additions & 0 deletions components/EchoListener.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { useEffect } from "react";

Check failure on line 1 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

organizeImports

Import statements differs from the output

Check failure on line 1 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

organizeImports

Import statements differs from the output
import { useDispatch, useSelector } from "react-redux";
import { getEcho } from "@/scripts/echo";
import { selectSyncVersion, selectUser } from "@/core/slices/authSlice";
import { DataCategories } from "@/core/DataCategoriesManager";
import { currentTeamsPage, resetTeams } from "@/core/slices/teamSlice";
import { resetSshSlice } from "@/core/slices/sshSlice";
import { addTeamMember, PageData, resetTeamMembers, teamCurrentPage } from "@/core/slices/teamsMembersSlice";
import { getMembers, getTeams } from "@/core/teamManager";
import { TeamType } from "@/types/Team";

Check failure on line 10 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/style/useImportType

All these imports are only used as types.

Check failure on line 10 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/style/useImportType

All these imports are only used as types.
import { addTeam as addTeamToSlice } from "@/core/slices/teamSlice";

export const EchoListener = () => {
const user = useSelector(selectUser);
const syncVersion = useSelector(selectSyncVersion);
const dispatch = useDispatch();
const teamCurrnetPage = useSelector(currentTeamsPage);

useEffect(() => {
if (!user?.id) return;

let channel: any;

Check failure on line 22 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.

Check failure on line 22 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.

const initEcho = async () => {
const echo = await getEcho();
const channelName = `sync.user.${user.id}`;
channel = echo.private(channelName);

channel.listen('.sync.nots', async (event: any) => {

Check failure on line 29 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.

Check failure on line 29 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
const data = JSON.parse(event?.message);
if (!data || event.user_id !== user.id) return;

if (data.type !== "report_new_sync_version") return;

if (syncVersion >= data.new_synchronization_version) return;

switch (data.category) {
case DataCategories.ssh:
dispatch(resetSshSlice());
break;
case DataCategories.team:
const maxPage = teamCurrnetPage || 1;

Check failure on line 42 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/correctness/noSwitchDeclarations

Other switch clauses can erroneously access this declaration. Wrap the declaration in a block to restrict its access to the switch clause.

Check failure on line 42 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/correctness/noSwitchDeclarations

Other switch clauses can erroneously access this declaration. Wrap the declaration in a block to restrict its access to the switch clause.
dispatch(
resetTeams(),
);

for (let page = 1; page <= maxPage; page++) {
try {
const data = await getTeams(page);
if (data?.teams && Array.isArray(data.teams)) {
data.teams.forEach((team: TeamType) => {
dispatch(addTeamToSlice({
team,
totalPages: data.total_pages,
currentPage: data.current_page,
}));
});
}
} catch (error) {
console.error(error);
break;
}
}
break;
case DataCategories.members:
dispatch(resetTeamMembers());

if (data?.team_id) {
const teamId = data.team_id;
const teamPageData = useSelector(PageData);
const maxPage = teamCurrentPage(teamPageData, teamId);

try {
for (let page = 1; page <= maxPage; page++) {
const response = await getMembers(teamId, 1);
if (response.ok) {
const membersData = await response.json();
membersData.members.forEach((member: any) => {

Check failure on line 78 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.

Check failure on line 78 in components/EchoListener.tsx

View workflow job for this annotation

GitHub Actions / quality

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
dispatch(addTeamMember({
members: member,
pageData: {
team_id: teamId, current_page: 1, total_pages: 1,
total_members: 0
},
}));
});
} else {
console.error(`Błąd ${response.status}: ${response.statusText}`);
}
}
} catch (error) {
console.error("Network error:", error);
}
}

break;
default:
console.warn("Nieobsługiwana kategoria:", data.category);
break;
}
});
};

initEcho();

return () => {
if (channel) {
channel.stopListening('.sync.nots');
}
};
}, [user?.id, syncVersion]);


return null;
};
4 changes: 2 additions & 2 deletions components/TeamAddModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export function TeamAddModal({ modalVisible, setModalVisible }: ServerModalProps

const save = async () => {
const data = await addTeam(teamName);
if (data.team) {
setModalVisible(!modalVisible);
setModalVisible(!modalVisible);
if (data?.team) {
dispatch(
createTeam({
team: data.team,
Expand Down
4 changes: 2 additions & 2 deletions components/TeamRemoveButtonAndModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ const TeamRemoveButtonAndModal: React.FC<TeamRemoveButtonAndModalProps> = ({ tea
};

const handleConfirmDelete = async () => {
const reponse = await deleteTeam(teamId);
const response = await deleteTeam(teamId);

if (reponse !== null) {
if (response !== null) {
dispatch(removeTeam(teamId));
}

Expand Down
7 changes: 7 additions & 0 deletions core/DataCategoriesManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum DataCategories {
team = "team",
gpg_keys = "keys",
users = "users",
ssh = "ssh",
members = "members",
}
21 changes: 20 additions & 1 deletion core/customFetch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { endpoint } from "@/constants/api";
import { endpoint } from "../constants/api";
import { read, store } from "./settings";
import {setSyncVersion} from "./slices/authSlice";

export async function fetchApi(url: string, options: RequestInit = {}) {
const headers = {
Expand Down Expand Up @@ -43,6 +44,8 @@ export async function fetchApi(url: string, options: RequestInit = {}) {
headers,
});
if (retryResponse.ok) {
await changeSyncVersion(response);

return retryResponse;
}
} catch (error) {
Expand All @@ -54,9 +57,25 @@ export async function fetchApi(url: string, options: RequestInit = {}) {
}
}

if (response.ok) {
await changeSyncVersion(response);
}

return response;
} catch (error) {
console.error("Fetch error:", error);
throw error;
}
}

export async function changeSyncVersion(response: Response) {
const clone = response.clone();
try {
const data = await clone.json();
if (data?.sync_version) {
setSyncVersion(data.sync_version);
}
} catch (err) {
console.warn("Nie udało się odczytać sync_version:", err);
}
}
11 changes: 10 additions & 1 deletion core/slices/authSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const authSlice = createSlice({
apiToken: null,
refreshToken: null,
isLoggedIn: false,
sync_version: null,
},
reducers: {
setUser: (state, action) => {
Expand All @@ -26,8 +27,16 @@ export const authSlice = createSlice({
state.refreshToken = null;
state.isLoggedIn = false;
},
setSyncVersion: (state, action) => {
state.sync_version = action.payload;
},

resetUser(state) {
state.user = null
}
},
});
export const selectUser = (state: { auth: { user: User } }) => state.auth.user;
export const selectSyncVersion = (state: { auth: { sync_version: number } }) => state.auth.sync_version;
export const selectIsLoggedIn = (state: { auth: { isLoggedIn: boolean } }) => state.auth.isLoggedIn;
export const { setUser, setApiToken, setRefreshToken, setIsLoggedIn, logout } = authSlice.actions;
export const { setUser, setApiToken, setRefreshToken, setIsLoggedIn, logout, setSyncVersion } = authSlice.actions;
7 changes: 7 additions & 0 deletions core/slices/sshSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ export const sshSlice = createSlice({
state.servers = array;
}
},


resetSshSlice(state){
state.servers = [];
}
},
});
setKeys: (state, action: { payload: KeyType[] }) => {
state.keys = action.payload;
},
Expand Down
Loading