diff --git a/src/app.tsx b/src/app.tsx index d6f59a7..9e081db 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,9 +1,14 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; +import RepositoryProvider from "./components/RepositoryProvider"; +import Home from "./views/Home"; function render() { ReactDOM.render( -

Hello from React!

, document.body + + + , + document.getElementById("root") ); } diff --git a/src/components/MediaList/index.tsx b/src/components/MediaList/index.tsx new file mode 100644 index 0000000..328f643 --- /dev/null +++ b/src/components/MediaList/index.tsx @@ -0,0 +1,12 @@ +import React, {FunctionComponent} from "react"; + +export type MediaListProps = { +} + +const MediaList: FunctionComponent = () => { + return ( +
+ ) +} + +export default MediaList \ No newline at end of file diff --git a/src/components/RepositoryProvider/index.tsx b/src/components/RepositoryProvider/index.tsx new file mode 100644 index 0000000..e3fa203 --- /dev/null +++ b/src/components/RepositoryProvider/index.tsx @@ -0,0 +1,42 @@ +import React, {FunctionComponent, useContext, useEffect, useState} from "react"; +import Repository from "../../repository"; +import {ipcRenderer} from 'electron'; + +const OPEN_REPOSITORY_MESSAGE_NAME = "MSG_OPEN_REPO" + +const RepositoryContext = React.createContext(null) + +export const useRepository = () => useContext(RepositoryContext) + +type RepositoryProviderProps = { +} + +const RepositoryProvider: FunctionComponent = ({children}) => { + const [repository, setRepository] = useState(null) + + useEffect(() => { + const listener = (event: any, data: any) => { + console.log(data) + const _path = data as string + if (_path) { + setRepository(new Repository(_path)) + } else { + setRepository(null) + } + } + + ipcRenderer.on(OPEN_REPOSITORY_MESSAGE_NAME, listener) + return () => { + // cleanup + ipcRenderer.removeListener(OPEN_REPOSITORY_MESSAGE_NAME, listener) + } + }, [setRepository]) + + return ( + + {children} + + ) +} + +export default RepositoryProvider \ No newline at end of file diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx new file mode 100644 index 0000000..c98635d --- /dev/null +++ b/src/components/Sidebar/index.tsx @@ -0,0 +1,37 @@ +import React, {FunctionComponent, useEffect, useState} from "react"; +import {useRepository} from "../RepositoryProvider"; +import {CountedTag} from "../../database/query"; + +export type SidebarProps = { +} + +const Sidebar: FunctionComponent = () => { + const repository = useRepository() + + const [tags, setTags] = useState([]) + + useEffect(() => { + console.log("sidebar use effect") + + if (repository) { + repository.get().then(d => { + console.log(d) + setTags(d.query().countedTags()) + }).catch(console.log) + } + }, [repository]) + + return ( +
+
    + { + tags.map(t => ( +
  • {t.name} ({t.count})
  • + )) + } +
+
+ ) +} + +export default Sidebar \ No newline at end of file diff --git a/src/database/config-keys.ts b/src/database/config-keys.ts index 8e5d8f3..f8c4f12 100644 --- a/src/database/config-keys.ts +++ b/src/database/config-keys.ts @@ -1,5 +1,5 @@ -const KEY_DIRECTORIES = "directories" -const KEY_FILES = "files" +export const KEY_DIRECTORIES = "directories" +export const KEY_FILES = "files" -const KEY_FILE_PATH = "path" -const KEY_FILE_TAGS = "tags" \ No newline at end of file +export const KEY_FILE_PATH = "path" +export const KEY_FILE_TAGS = "tags" \ No newline at end of file diff --git a/src/database/database.ts b/src/database/database.ts index 6956cb2..a38f6b9 100644 --- a/src/database/database.ts +++ b/src/database/database.ts @@ -1,4 +1,9 @@ -class Database { +import {KEY_DIRECTORIES, KEY_FILES} from "./config-keys"; +import {Directory} from "./directory"; +import {MediaFile} from "./file"; +import {Query} from "./query"; + +export class Database { private directories: Directory[] private files: MediaFile[] @@ -70,4 +75,4 @@ class Database { return obj } -} +} \ No newline at end of file diff --git a/src/database/directory.ts b/src/database/directory.ts index 3b3561b..2b74ed7 100644 --- a/src/database/directory.ts +++ b/src/database/directory.ts @@ -1,4 +1,4 @@ -class Directory { +export class Directory { private readonly path: string constructor(path: string) { diff --git a/src/database/file-type.ts b/src/database/file-type.ts index badded5..85a037e 100644 --- a/src/database/file-type.ts +++ b/src/database/file-type.ts @@ -1,10 +1,10 @@ -enum MediaFileType { +export enum MediaFileType { unknown, video, image } -function FileTypeFromExtension(name: string): MediaFileType { +export function FileTypeFromExtension(name: string): MediaFileType { while (name.indexOf(".") >= 0) { name = name.substring(name.indexOf(".") + 1) } diff --git a/src/database/file.ts b/src/database/file.ts index 4c95319..a80c540 100644 --- a/src/database/file.ts +++ b/src/database/file.ts @@ -1,4 +1,7 @@ -class MediaFile { +import {FileTypeFromExtension, MediaFileType} from "./file-type"; +import {KEY_FILE_PATH, KEY_FILE_TAGS} from "./config-keys"; + +export class MediaFile { private readonly path: string private readonly type: MediaFileType private tags: string[] diff --git a/src/database/query.ts b/src/database/query.ts index 40495c9..c392b9a 100644 --- a/src/database/query.ts +++ b/src/database/query.ts @@ -1,10 +1,12 @@ -type CountedTag = { +import {MediaFile} from "./file"; +import {MediaFileType} from "./file-type"; + +export type CountedTag = { name: string, count: number } - -class Query { +export class Query { private readonly files: MediaFile[] public constructor(files: MediaFile[]) { diff --git a/src/index.html b/src/index.html index 25d360e..299a2c8 100644 --- a/src/index.html +++ b/src/index.html @@ -5,5 +5,7 @@ Tagify +
+
diff --git a/src/index.ts b/src/index.ts index 5e67927..58b02e7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,11 @@ -import { app, BrowserWindow } from 'electron'; +import {app, BrowserWindow, dialog, Menu} from 'electron'; // This allows TypeScript to pick up the magic constant that's auto-generated by Forge's Webpack // plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on // whether you're running in development or production). declare const MAIN_WINDOW_WEBPACK_ENTRY: string; +export const OPEN_REPOSITORY_MESSAGE_NAME = "MSG_OPEN_REPO" + // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (require('electron-squirrel-startup')) { // eslint-disable-line global-require app.quit(); @@ -13,7 +15,11 @@ const createWindow = (): void => { // Create the browser window. const mainWindow = new BrowserWindow({ height: 600, - width: 800, + width: 1300, + webPreferences: { + nodeIntegration: true, + contextIsolation: false + } }); // and load the index.html of the app. @@ -21,6 +27,35 @@ const createWindow = (): void => { // Open the DevTools. mainWindow.webContents.openDevTools(); + + const menu = Menu.buildFromTemplate([ + { + label: 'File', + submenu: [ + { + label: 'Open Repository', + click: menuItem => { + dialog.showOpenDialog({ + title: "Open Repository", + properties: [ + "openDirectory", + ] + }).then(result => { + if (result.canceled || result.filePaths.length != 1) { + return + } + mainWindow.webContents.send(OPEN_REPOSITORY_MESSAGE_NAME, result.filePaths[0]) + }) + } + }, + { + label: 'Exit', + click: menuItem => app.quit() + } + ] + } + ]) + Menu.setApplicationMenu(menu); }; // This method will be called when Electron has finished diff --git a/src/repository/index.ts b/src/repository/index.ts index 231e9d5..9d475ce 100644 --- a/src/repository/index.ts +++ b/src/repository/index.ts @@ -1,6 +1,8 @@ import * as fsPromises from "fs/promises"; +import {Database} from "../database/database"; +import {FileTypeFromExtension, MediaFileType} from "../database/file-type"; -const DB_FILE = ".tagdb.json" +const DB_FILE = ".tagdb" class Repository { private readonly path: string @@ -57,4 +59,6 @@ class Repository { return untagged.filter((v, i, s) => s.indexOf(v) == i) } -} \ No newline at end of file +} + +export default Repository \ No newline at end of file diff --git a/src/views/Home/index.tsx b/src/views/Home/index.tsx new file mode 100644 index 0000000..ba3d5d9 --- /dev/null +++ b/src/views/Home/index.tsx @@ -0,0 +1,23 @@ +import React, {FunctionComponent, useState} from "react"; +import Sidebar from "../../components/Sidebar"; +import MediaList from "../../components/MediaList"; +import {MediaFile} from "../../database/file"; + +export type HomeProps = { +} + +const Home: FunctionComponent = () => { + + const [selected, setSelected] = useState(null) + + return ( +
+ + { !selected && + + } +
+ ) +} + +export default Home \ No newline at end of file diff --git a/webpack.renderer.config.js b/webpack.renderer.config.js index fee66bd..1ce355e 100644 --- a/webpack.renderer.config.js +++ b/webpack.renderer.config.js @@ -14,4 +14,5 @@ module.exports = { resolve: { extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'] }, + target: 'electron-renderer' };