mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-02 10:03:28 +00:00
temp icon, color tweaks and menu stuff
This commit is contained in:
parent
b65771351e
commit
fb0e9db591
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -1,3 +1,5 @@
|
|||
{
|
||||
"cSpell.words": ["ipfs", "repr", "tailwindcss"]
|
||||
"cSpell.words": ["ipfs", "repr", "tailwindcss"],
|
||||
"rust-analyzer.procMacro.enable": true,
|
||||
"rust-analyzer.diagnostics.enableExperimental": false,
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-dropzone": "^11.3.4",
|
||||
"react-hotkeys-hook": "^3.4.4",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-spline": "^1.2.1",
|
||||
"react-virtualized": "^9.22.3",
|
||||
|
|
Binary file not shown.
|
@ -1,13 +1,54 @@
|
|||
use tauri::{CustomMenuItem, Menu, Submenu};
|
||||
use tauri::{CustomMenuItem, Menu, MenuItem, Submenu, WindowMenuEvent, Wry};
|
||||
|
||||
pub(crate) fn get_menu() -> Menu {
|
||||
let quit = CustomMenuItem::new("quit".to_string(), "Quit");
|
||||
let close = CustomMenuItem::new("close".to_string(), "Close");
|
||||
let submenu = Submenu::new("File", Menu::new().add_item(quit).add_item(close));
|
||||
// let quit = CustomMenuItem::new("quit".to_string(), "Quit");
|
||||
// let close = CustomMenuItem::new("close".to_string(), "Close");
|
||||
// let jeff = CustomMenuItem::new("jeff".to_string(), "Jeff");
|
||||
// let submenu = Submenu::new(
|
||||
// "File",
|
||||
// Menu::new().add_item(quit).add_item(close).add_item(jeff),
|
||||
// );
|
||||
|
||||
let file = Submenu::new(
|
||||
"File",
|
||||
Menu::new()
|
||||
.add_item(CustomMenuItem::new("quit".to_string(), "Quit"))
|
||||
.add_item(CustomMenuItem::new("close".to_string(), "Close")),
|
||||
);
|
||||
let edit = Submenu::new(
|
||||
"Edit",
|
||||
Menu::new()
|
||||
.add_item(CustomMenuItem::new("jeff".to_string(), "Copy"))
|
||||
.add_item(CustomMenuItem::new("jeffd".to_string(), "Paste")),
|
||||
);
|
||||
let view = Submenu::new(
|
||||
"View",
|
||||
Menu::new()
|
||||
.add_item(CustomMenuItem::new(
|
||||
"command_pallete".to_string(),
|
||||
"Command Pallete",
|
||||
))
|
||||
.add_item(CustomMenuItem::new("jeffd".to_string(), "Layout")),
|
||||
);
|
||||
|
||||
let menu = Menu::new()
|
||||
// .add_native_item(MenuItem::Copy)
|
||||
// .add_item(CustomMenuItem::new("hide", "Hide"))
|
||||
.add_submenu(submenu);
|
||||
.add_native_item(MenuItem::Copy)
|
||||
.add_item(CustomMenuItem::new("about".to_string(), "About SpaceDrive"))
|
||||
.add_submenu(file)
|
||||
.add_submenu(edit)
|
||||
.add_submenu(view);
|
||||
|
||||
menu
|
||||
}
|
||||
|
||||
pub(crate) fn handle_menu_event(event: WindowMenuEvent<Wry>) {
|
||||
match event.menu_item_id() {
|
||||
"quit" => {
|
||||
std::process::exit(0);
|
||||
}
|
||||
"close" => {
|
||||
event.window().close().unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,12 +33,13 @@ fn main() {
|
|||
// block_on(filesystem::device::discover_storage_devices()).unwrap();
|
||||
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
.setup(|_app| {
|
||||
// let main_window = app.get_window("main").unwrap();
|
||||
// // would need to emit this elsewhere in my Rust code
|
||||
// main_window.emit("my-event", "payload");
|
||||
Ok(())
|
||||
})
|
||||
.on_menu_event(|event| menu::handle_menu_event(event))
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::get_config,
|
||||
commands::scan_dir,
|
||||
|
|
16
src/App.tsx
16
src/App.tsx
|
@ -9,6 +9,9 @@ import { invoke } from '@tauri-apps/api';
|
|||
import { DebugGlobalStore } from './store/Debug';
|
||||
import { useGlobalEvents } from './hooks/useGlobalEvents';
|
||||
import { AppState, useAppState } from './store/app';
|
||||
import { Modal } from './components/layout/Modal';
|
||||
import { useKey, useKeyBindings } from 'rooks';
|
||||
// import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
export default function App() {
|
||||
useGlobalEvents();
|
||||
|
@ -16,6 +19,10 @@ export default function App() {
|
|||
invoke<AppState>('get_config').then((state) => useAppState.getState().update(state));
|
||||
}, []);
|
||||
|
||||
// useHotkeys('command+q', () => {
|
||||
// process.exit();
|
||||
// });
|
||||
|
||||
return (
|
||||
<Router>
|
||||
<div className="flex flex-col select-none h-screen rounded-xl border border-gray-200 dark:border-gray-450 bg-white text-gray-900 dark:text-white dark:bg-gray-800 overflow-hidden ">
|
||||
|
@ -26,17 +33,18 @@ export default function App() {
|
|||
<div className="relative w-full flex bg-gray-50 dark:bg-gray-800">
|
||||
<Switch>
|
||||
<Route exact path="/">
|
||||
<Redirect to="/settings" />
|
||||
</Route>
|
||||
<Route path="/settings">
|
||||
<SettingsScreen />
|
||||
<Redirect to="/explorer" />
|
||||
</Route>
|
||||
<Route path="/explorer">
|
||||
<ExplorerScreen />
|
||||
</Route>
|
||||
<Route path="/settings">
|
||||
<SettingsScreen />
|
||||
</Route>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
{/* <Modal /> */}
|
||||
</div>
|
||||
</Router>
|
||||
);
|
||||
|
|
|
@ -3,7 +3,7 @@ import clsx from 'clsx';
|
|||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { IFile } from '../../types';
|
||||
import byteSize from 'pretty-bytes';
|
||||
import { useKey } from 'rooks';
|
||||
import { useKey, useOnWindowResize, useWindowSize } from 'rooks';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import {
|
||||
useCurrentDir,
|
||||
|
@ -43,6 +43,12 @@ export const FileList: React.FC<{}> = (props) => {
|
|||
const VList = useRef<null | List>(null);
|
||||
const currentDir = useCurrentDir();
|
||||
|
||||
// useOnWindowResize((e) => {
|
||||
|
||||
// })
|
||||
|
||||
const size = useWindowSize();
|
||||
|
||||
const explorer = useExplorerStore.getState();
|
||||
|
||||
const seletedRowIndex = useSelectedFileIndex(currentDir?.id as number);
|
||||
|
@ -89,7 +95,7 @@ export const FileList: React.FC<{}> = (props) => {
|
|||
};
|
||||
|
||||
const width = (tableContainer.current?.getBoundingClientRect().width || 0) - 30;
|
||||
const height = (tableContainer.current?.getBoundingClientRect().height || 0) - 30;
|
||||
const height = (tableContainer.current?.getBoundingClientRect().height || 0) - 140;
|
||||
|
||||
return useMemo(
|
||||
() => (
|
||||
|
@ -123,7 +129,7 @@ export const FileList: React.FC<{}> = (props) => {
|
|||
/>
|
||||
</div>
|
||||
),
|
||||
[currentDir?.id, tableContainer.current]
|
||||
[size.innerWidth, currentDir?.id, tableContainer.current]
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ const MetaItem = (props: MetaItemProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
const Divider = () => <div className="w-full my-1 h-[1px] bg-gray-700" />;
|
||||
const Divider = () => <div className="w-full my-1 h-[1px] bg-gray-100 dark:bg-gray-700" />;
|
||||
|
||||
export const Inspector = () => {
|
||||
const selectedFile = useSelectedFile();
|
||||
|
@ -30,7 +30,7 @@ export const Inspector = () => {
|
|||
|
||||
return (
|
||||
<Transition
|
||||
show={isOpen}
|
||||
show={true}
|
||||
enter="transition-translate ease-in-out duration-200"
|
||||
enterFrom="translate-x-64"
|
||||
enterTo="translate-x-0"
|
||||
|
@ -38,23 +38,25 @@ export const Inspector = () => {
|
|||
leaveFrom="translate-x-0"
|
||||
leaveTo="translate-x-64"
|
||||
>
|
||||
<div className="h-full w-60 right-0 top-0 m-2">
|
||||
<div className="flex flex-col overflow-hidden h-full rounded-lg bg-gray-700 shadow-lg select-text">
|
||||
<div className="h-32 bg-gray-750 w-full flex justify-center items-center">
|
||||
<img
|
||||
src={convertFileSrc(
|
||||
`${useAppState.getState().file_type_thumb_dir}/${
|
||||
file?.is_dir ? 'folder' : file?.extension
|
||||
}.png`
|
||||
)}
|
||||
className="h-24"
|
||||
/>
|
||||
<div className="h-full w-60 right-0 top-0 m-2 border border-gray-100 dark:border-gray-850 rounded-lg ">
|
||||
{!!file && (
|
||||
<div className="flex flex-col overflow-hidden h-full rounded-lg bg-white dark:bg-gray-700 select-text">
|
||||
<div className="h-32 bg-gray-50 dark:bg-gray-750 rounded-t-lg w-full flex justify-center items-center">
|
||||
<img
|
||||
src={convertFileSrc(
|
||||
`${useAppState.getState().file_type_thumb_dir}/${
|
||||
file?.is_dir ? 'folder' : file?.extension
|
||||
}.png`
|
||||
)}
|
||||
className="h-24"
|
||||
/>
|
||||
</div>
|
||||
<h3 className="font-bold p-3 text-base">{file?.name}</h3>
|
||||
<MetaItem title="Checksum" value={file?.meta_checksum as string} />
|
||||
<Divider />
|
||||
<MetaItem title="Uri" value={file?.uri as string} />
|
||||
</div>
|
||||
<h3 className="font-bold p-3 text-base">{file?.name}</h3>
|
||||
<MetaItem title="Checksum" value={file?.meta_checksum as string} />
|
||||
<Divider />
|
||||
<MetaItem title="Uri" value={file?.uri as string} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Transition>
|
||||
);
|
||||
|
|
|
@ -6,19 +6,36 @@ import {
|
|||
PhotographIcon,
|
||||
ServerIcon
|
||||
} from '@heroicons/react/solid';
|
||||
import { Folder, Planet } from 'phosphor-react';
|
||||
import {
|
||||
Book,
|
||||
Camera,
|
||||
Circle,
|
||||
CirclesFour,
|
||||
Folder,
|
||||
HandGrabbing,
|
||||
HardDrive,
|
||||
HardDrives,
|
||||
MonitorPlay,
|
||||
Package,
|
||||
Planet
|
||||
} from 'phosphor-react';
|
||||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { Dropdown } from '../primative/Dropdown';
|
||||
import { DefaultProps } from '../primative/types';
|
||||
|
||||
const tabs = [
|
||||
// { name: 'Spaces', icon: Planet, uri: '/spaces' },
|
||||
{ name: 'Explorer', icon: Folder, uri: '/explorer' },
|
||||
{ name: 'Photos', icon: PhotographIcon, uri: '/photos' },
|
||||
{ name: 'Storage', icon: ServerIcon, uri: '/settings' }
|
||||
// { name: 'Settings', icon: CogIcon, uri: '/settings' }
|
||||
];
|
||||
const tabs = {
|
||||
'': [
|
||||
{ name: 'Spaces', icon: CirclesFour, uri: '/spaces' },
|
||||
{ name: 'Explorer', icon: Folder, uri: '/explorer' },
|
||||
{ name: 'Media', icon: MonitorPlay, uri: '/photos' }
|
||||
],
|
||||
'Locations': [
|
||||
{ name: 'Macintosh HD', icon: HardDrive, uri: '/x' },
|
||||
{ name: 'LaCie 2TB', icon: HardDrive, uri: '/xs' },
|
||||
{ name: 'Seagate 16TB', icon: HardDrive, uri: '/xss' }
|
||||
]
|
||||
};
|
||||
|
||||
interface SidebarProps extends DefaultProps {}
|
||||
|
||||
|
@ -29,24 +46,34 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
|
|||
buttonProps={{
|
||||
justifyLeft: true,
|
||||
className:
|
||||
'mb-1 shadow flex-shrink-0 w-[175px] dark:bg-gray-550 dark:hover:!bg-gray-500 dark:hover:!border-gray-450',
|
||||
'mb-1 !bg-gray-50 border-gray-150 hover:!bg-gray-100 flex-shrink-0 w-[175px] dark:bg-gray-550 dark:hover:!bg-gray-500 dark:hover:!border-gray-450',
|
||||
variant: 'gray'
|
||||
}}
|
||||
// buttonIcon={<Book weight="bold" className="w-4 h-4 mt-0.5 mr-1" />}
|
||||
buttonText="Jamie's Library"
|
||||
items={[[{ name: `Jamie's Library` }, { name: 'Subto' }], [{ name: 'Add Library' }]]}
|
||||
/>
|
||||
|
||||
{tabs.map((button, index) => (
|
||||
<NavLink
|
||||
key={index}
|
||||
className="max-w rounded px-2 py-1 flex flex-row items-center hover:bg-gray-200 dark:hover:bg-gray-600 text-sm"
|
||||
activeClassName="bg-gray-200 hover:bg-gray-200 dark:bg-gray-500 dark:hover:bg-gray-500"
|
||||
to={button.uri}
|
||||
>
|
||||
{button.icon && <button.icon className="w-4 h-4 mr-2" />}
|
||||
{button.name}
|
||||
</NavLink>
|
||||
))}
|
||||
{Object.keys(tabs).map((name) => {
|
||||
return (
|
||||
<div className="">
|
||||
{name && (
|
||||
<div className="text-xs font-semibold text-gray-300 ml-1 mb-1 mt-5">{name}</div>
|
||||
)}
|
||||
{tabs[name as keyof typeof tabs].map((button, index) => (
|
||||
<NavLink
|
||||
key={index}
|
||||
className="max-w text-gray-550 dark:text-gray-150 rounded-md px-2 py-1 flex flex-row items-center hover:bg-gray-100 dark:hover:bg-gray-600 text-sm"
|
||||
activeClassName="!bg-primary !text-white hover:bg-primary dark:hover:bg-primary"
|
||||
to={button.uri}
|
||||
>
|
||||
{button.icon && <button.icon weight="bold" className="w-4 h-4 mr-2 " />}
|
||||
{button.name}
|
||||
</NavLink>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
11
src/components/layout/Modal.tsx
Normal file
11
src/components/layout/Modal.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
|
||||
export interface ModalProps {}
|
||||
|
||||
export const Modal = (props: ModalProps) => {
|
||||
return (
|
||||
<div className="w-screen h-screen p-5 absolute t-0 bg-black bg-opacity-30">
|
||||
<div className="w-full h-full bg-white rounded-lg shadow-xl"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -19,7 +19,8 @@ import {
|
|||
HouseSimple,
|
||||
List,
|
||||
SquaresFour,
|
||||
Tag
|
||||
Tag,
|
||||
TerminalWindow
|
||||
} from 'phosphor-react';
|
||||
import React from 'react';
|
||||
import { useExplorerStore } from '../../store/explorer';
|
||||
|
@ -43,7 +44,7 @@ const TopBarButton: React.FC<TopBarButtonProps> = ({ icon: Icon, ...props }) =>
|
|||
<button
|
||||
{...props}
|
||||
className={clsx(
|
||||
'mr-[1px] py-0.5 px-0.5 text-md font-medium dark:bg-gray-550 dark:hover:bg-gray-600 dark:active:bg-gray-500 rounded-md transition-colors duration-100',
|
||||
'mr-[1px] py-0.5 px-0.5 text-md font-medium hover:bg-gray-150 dark:bg-gray-550 dark:hover:bg-gray-600 dark:active:bg-gray-500 rounded-md transition-colors duration-100',
|
||||
{
|
||||
'rounded-r-none rounded-l-none': props.group && !props.left && !props.right,
|
||||
'rounded-r-none': props.group && props.left,
|
||||
|
@ -53,7 +54,7 @@ const TopBarButton: React.FC<TopBarButtonProps> = ({ icon: Icon, ...props }) =>
|
|||
props.className
|
||||
)}
|
||||
>
|
||||
<Icon className="m-0.5 w-5 h-5 dark:text-gray-150" />
|
||||
<Icon weight={'regular'} className="m-0.5 w-5 h-5 text-gray-450 dark:text-gray-150" />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
@ -64,7 +65,7 @@ export const TopBar: React.FC<TopBarProps> = (props) => {
|
|||
<>
|
||||
<div
|
||||
data-tauri-drag-region
|
||||
className="flex flex-shrink-0 h-11 -mt-0.5 max-w items-center border-b bg-gray-100 dark:bg-gray-550 border-gray-100 dark:border-gray-900 shadow-sm"
|
||||
className="flex flex-shrink-0 h-[2.95rem] -mt-0.5 max-w items-center border-b bg-gray-50 dark:bg-gray-550 border-gray-100 dark:border-gray-900 shadow-sm"
|
||||
>
|
||||
<div className="mr-32 ml-1 ">
|
||||
<TrafficLights
|
||||
|
@ -86,15 +87,16 @@ export const TopBar: React.FC<TopBarProps> = (props) => {
|
|||
<div className="flex mx-8 space-x-2">
|
||||
<TopBarButton icon={Tag} />
|
||||
<TopBarButton icon={FolderPlus} />
|
||||
<TopBarButton icon={TerminalWindow} />
|
||||
</div>
|
||||
<div className="relative flex h-7">
|
||||
<input
|
||||
placeholder="Search"
|
||||
className="w-32 focus:w-52 text-xs p-2 rounded-md outline-none focus:ring-2 placeholder-gray-600 dark:placeholder-gray-300 bg-gray-50 dark:bg-gray-500 dark:border-gray-500 focus:ring-gray-100 dark:focus:ring-gray-600 transition-all"
|
||||
className="w-32 focus:w-52 text-sm p-3 rounded-md outline-none focus:ring-2 placeholder-gray-400 dark:placeholder-gray-300 bg-gray-50 border border-gray-250 dark:bg-gray-500 dark:border-gray-500 focus:ring-gray-100 dark:focus:ring-gray-600 transition-all"
|
||||
/>
|
||||
<div className="space-x-1 absolute top-[1px] right-1">
|
||||
<Shortcut chars="⌘" />
|
||||
<Shortcut chars="S" />
|
||||
<Shortcut chars="⌘S" />
|
||||
{/* <Shortcut chars="S" /> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex mx-8 space-x-2">
|
||||
|
|
|
@ -16,6 +16,7 @@ export interface DropdownProps extends DefaultOptions {
|
|||
items: Section[];
|
||||
buttonText: string;
|
||||
buttonProps: ButtonProps;
|
||||
buttonIcon?: any;
|
||||
}
|
||||
|
||||
export const Dropdown: React.FC<DropdownProps> = (props) => {
|
||||
|
@ -25,6 +26,7 @@ export const Dropdown: React.FC<DropdownProps> = (props) => {
|
|||
<div>
|
||||
<Menu.Button className="outline-none">
|
||||
<Button size="sm" {...props.buttonProps}>
|
||||
{props.buttonIcon}
|
||||
{props.buttonText}
|
||||
<div className="flex-grow" />
|
||||
<ChevronDownIcon
|
||||
|
|
|
@ -27,11 +27,11 @@ export const SettingsScreen: React.FC<{}> = () => {
|
|||
<div className="px-5">
|
||||
{/* <FileList files={dummyIFile} /> */}
|
||||
{/* <Spline scene={WINDOWS_SCENE} /> */}
|
||||
{/* <iframe
|
||||
<iframe
|
||||
src="https://my.spline.design/windowscopy-8e92a2e9b7cb4d9237100441e8c4f688/"
|
||||
width="100%"
|
||||
height="100%"
|
||||
></iframe> */}
|
||||
></iframe>
|
||||
<div className="flex space-x-2 mt-4">
|
||||
<InputContainer
|
||||
title="Quick scan directory"
|
||||
|
|
|
@ -31,7 +31,7 @@ module.exports = {
|
|||
},
|
||||
gray: {
|
||||
DEFAULT: '#505468',
|
||||
50: '#F1F1F4',
|
||||
50: '#F9F9F9',
|
||||
100: '#E8E9ED',
|
||||
150: '#E0E1E6',
|
||||
200: '#D8DAE3',
|
||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -2084,6 +2084,11 @@ hosted-git-info@^2.1.4:
|
|||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
|
||||
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
|
||||
|
||||
hotkeys-js@3.8.7:
|
||||
version "3.8.7"
|
||||
resolved "https://registry.yarnpkg.com/hotkeys-js/-/hotkeys-js-3.8.7.tgz#c16cab978b53d7242f860ca3932e976b92399981"
|
||||
integrity sha512-ckAx3EkUr5XjDwjEHDorHxRO2Kb7z6Z2Sxul4MbBkN8Nho7XDslQsgMJT+CiJ5Z4TgRxxvKHEpuLE3imzqy4Lg==
|
||||
|
||||
hsl-regex@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e"
|
||||
|
@ -3389,6 +3394,13 @@ react-dropzone@^11.3.4:
|
|||
file-selector "^0.2.2"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-hotkeys-hook@^3.4.4:
|
||||
version "3.4.4"
|
||||
resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-3.4.4.tgz#52ba5d8ef5e47cc2e776c70a9036d518e0993d51"
|
||||
integrity sha512-vaORq07rWgmuF3owWRhgFV/3VL8/l2q9lz0WyVEddJnWTtKW+AOgU5YgYKuwN6h6h7bCcLG3MFsJIjCrM/5DvQ==
|
||||
dependencies:
|
||||
hotkeys-js "3.8.7"
|
||||
|
||||
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
|
|
Loading…
Reference in a new issue