From 4a4cfd944fe7300771bb6d559acc0ab525f0159a Mon Sep 17 00:00:00 2001 From: Spliterash Date: Thu, 17 Oct 2024 14:46:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=B2=D1=8B=D0=B1=D1=80=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D1=83=20=D0=BA=D1=83?= =?UTF-8?q?=D0=B4=D0=B0=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B6=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B2=D0=B8=D0=B4=D0=BE=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/package-lock.json | 16 ++++ front/package.json | 1 + front/src/App.tsx | 8 +- front/src/consts.ts | 5 +- front/src/panels/GroupSelect.tsx | 95 +++++++++++++++++++ front/src/panels/Home.tsx | 16 +++- .../video/controller/VideoController.kt | 2 +- .../controller/request/VideoSaveRequest.kt | 2 + .../video/service/VideoSaveService.kt | 7 +- 9 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 front/src/panels/GroupSelect.tsx diff --git a/front/package-lock.json b/front/package-lock.json index 4f61597..b7ba5e2 100644 --- a/front/package-lock.json +++ b/front/package-lock.json @@ -17,6 +17,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@types/node": "^22.7.6", "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@typescript-eslint/eslint-plugin": "^6.14.0", @@ -2121,6 +2122,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/node": { + "version": "22.7.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", + "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", + "dev": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, "node_modules/@types/prop-types": { "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", @@ -5826,6 +5836,12 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", diff --git a/front/package.json b/front/package.json index 04a6f47..1498f16 100644 --- a/front/package.json +++ b/front/package.json @@ -22,6 +22,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@types/node": "^22.7.6", "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@typescript-eslint/eslint-plugin": "^6.14.0", diff --git a/front/src/App.tsx b/front/src/App.tsx index 5d2a341..139b98d 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -4,17 +4,19 @@ import {ScreenSpinner, SplitCol, SplitLayout} from '@vkontakte/vkui'; import {Home} from './panels'; import {APP_ID, HashInput} from "./consts.ts"; import Denied from "./panels/Denied.tsx"; -import bridge, {ReceiveData} from "@vkontakte/vk-bridge"; +import bridge, {ReceiveData, UserInfo} from "@vkontakte/vk-bridge"; // Поебать const hash: HashInput = JSON.parse(decodeURI(window.location.hash.substring(1))) export const App = () => { const [token, setToken] = useState(null) const [popout, setPopout] = useState(); + const [user, setUser] = useState(null) const [denied, setDenied] = useState(false) async function fetchData() { await askPermissions() + setUser(await bridge.send('VKWebAppGetUserInfo')) setPopout(null) } @@ -48,8 +50,8 @@ export const App = () => { function component() { if (denied) return - else if (popout == null) - return + else if (popout == null && user != null) + return else return
} diff --git a/front/src/consts.ts b/front/src/consts.ts index b92458e..051450c 100644 --- a/front/src/consts.ts +++ b/front/src/consts.ts @@ -1,6 +1,7 @@ import bridge from "@vkontakte/vk-bridge"; export const APP_ID = 52483593 +export const VK_API_VERSION = "5.199" export interface HashInput { id: string @@ -16,10 +17,12 @@ export interface VideoInfo { export interface VideoSaveRequest { // ID запроса в моей системе id: string + userId: number + groupId?: number // Куда перелить uploadUrl: string } -export function closeApp(){ +export function closeApp() { bridge.send("VKWebAppClose") } \ No newline at end of file diff --git a/front/src/panels/GroupSelect.tsx b/front/src/panels/GroupSelect.tsx new file mode 100644 index 0000000..52d85d8 --- /dev/null +++ b/front/src/panels/GroupSelect.tsx @@ -0,0 +1,95 @@ +import bridge, {GroupInfo, UserInfo} from "@vkontakte/vk-bridge"; +import {VK_API_VERSION} from "../consts.ts"; +import {ChangeEvent, useState} from "react"; +import {Avatar, CustomSelectOption, FormItem, Select} from "@vkontakte/vkui"; +import {CustomSelectOptionInterface} from "@vkontakte/vkui/src/components/CustomSelect/CustomSelect.tsx"; + + +export interface GroupSelectProps { + token: string, + user: UserInfo, + setValue: (current: GroupInfo | null) => void +} + +const User: CustomSelectOptionInterface = { + value: "user", + label: "Свой аккаунт", +} + +interface Group extends CustomSelectOptionInterface { + group: GroupInfo +} + +type Row = typeof User | Group + +export default function GroupSelect({token, setValue, user}: GroupSelectProps) { + const [nativeValue, setNativeValue] = useState("user") + const [listOptions, setListOptions] = useState([User]) + const [loading, setLoading] = useState(false) + + async function checkGroups() { + if (loading) return + if (listOptions.length > 1) return + setLoading(true) + try { + const result = await bridge.send("VKWebAppCallAPIMethod", { + method: "groups.get", + params: { + access_token: token, + v: VK_API_VERSION, + filter: "admin,editor", + extended: 1 + } + }) + const groups = result.response.items as GroupInfo[] + const newList: Row[] = groups.map(function (g: GroupInfo): Group { + return { + value: g.id, + label: g.name, + group: g + } + }) + newList.unshift(User) + + setListOptions(newList) + } finally { + setLoading(false) + } + } + + function handleChange(event: ChangeEvent) { + const value = event.target.value; + setNativeValue(event.target.value) + + const select = listOptions.find(e => e.value == value) + + if (!select) return + else if (select == User) setValue(null) + else setValue(select.group) + } + + function getAvatar(option: Row): string { + if (option == User) return user.photo_100 + else return option.group.photo_100 + } + + return +