├── .editorconfig ├── .erb ├── configs │ ├── .eslintrc │ ├── webpack.config.base.ts │ ├── webpack.config.eslint.ts │ ├── webpack.config.main.prod.ts │ ├── webpack.config.preload.dev.ts │ ├── webpack.config.renderer.dev.dll.ts │ ├── webpack.config.renderer.dev.ts │ ├── webpack.config.renderer.prod.ts │ └── webpack.paths.ts ├── img │ ├── erb-banner.svg │ ├── erb-logo.png │ └── palette-sponsor-banner.svg ├── mocks │ └── fileMock.js ├── note.MD └── scripts │ ├── .eslintrc │ ├── check-build-exists.ts │ ├── check-native-dep.js │ ├── check-node-env.js │ ├── check-port-in-use.js │ ├── clean.js │ ├── delete-source-maps.js │ ├── electron-rebuild.js │ ├── link-modules.ts │ └── notarize.js ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github ├── FUNDING.yml ├── config.yml ├── note.MD └── workflows │ └── publish.yml ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json ├── note.MD └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets ├── Attributions.md ├── assets.d.ts ├── entitlements.mac.plist ├── gear.png ├── icon.icns ├── icon.ico ├── icon.png ├── icon.svg ├── icons │ ├── 1024x1024.png │ ├── 128x128.png │ ├── 16x16.png │ ├── 24x24.png │ ├── 256x256.png │ ├── 32x32.png │ ├── 48x48.png │ ├── 512x512.png │ ├── 64x64.png │ └── 96x96.png ├── lightweight-48.png ├── note.MD ├── restore-window-64.png ├── restore-window.png └── settings-gear.png ├── help ├── FAQ.md ├── FilterAndSortList.md ├── InstallHelp.md ├── MyAnimeListToAniListTransfer.md ├── Other.md ├── Setup.md └── Updates.md ├── images ├── banner │ ├── AniCour.png │ ├── AniCourBanner.png │ ├── AniCourBannerWide.png │ └── AniCourSmall.png ├── help │ ├── AniCourAdvancedFiltering.png │ ├── AniCourInstallationMenu1.png │ ├── AniCourInstallationMenu2.png │ ├── AniCourNoCodeSigning.png │ ├── AniCourNoCodeSigningInitial.png │ ├── AniCourSaveInformation.png │ ├── AniCourSettingsButton.png │ ├── AniCourSettingsMenu.png │ ├── AniCourSetupFinished.png │ ├── AniCourSync.png │ ├── AniCourTokenButton.png │ ├── AniCourTokenLoginPage.png │ ├── AniCourTokenPage.png │ ├── AniCourUsernameAndTokenMessage.png │ ├── AniCourUsernameInput.png │ ├── AniListProfilePage.png │ ├── AniListProfilePageTooltip.png │ └── AniListTokenTooltip.png ├── readme │ ├── Advanced │ │ ├── Advanced.png │ │ ├── AdvancedCropped.png │ │ ├── AniCourAdvancedInfo2.png │ │ └── AniCourTrailer.png │ ├── AniCourAdvancedInfo1.png │ ├── AniCourAdvancedInfo2.png │ ├── AniCourAdvancedSideBySide.png │ ├── AniCourAdvancedThemes2.png │ ├── AniCourAdvancedThemes3.png │ ├── AniCourCompact2.jpg │ ├── AniCourCompactAndList.png │ ├── AniCourCompactFiltered.jpg │ ├── AniCourContextMenu.png │ ├── AniCourGridView.png │ ├── AniCourGridView2.png │ ├── AniCourGridView3.png │ ├── AniCourListView.png │ ├── AniCourListViewFiltered.png │ ├── AniCourNewListView.png │ ├── AniCourNews.png │ ├── AniCourNews2.png │ ├── AniCourNews3.png │ ├── AniCourNewsAdvanced.png │ ├── AniCourNewsSideBySide.png │ ├── AniCourSearch.png │ ├── AniCourSeasons.png │ ├── AniCourTrailer.png │ ├── News │ │ ├── AniCourNews.png │ │ ├── AniCourNewsAdvanced.png │ │ ├── News.png │ │ └── NewsCropped.png │ ├── Search │ │ ├── AniCourSearch.png │ │ ├── AniCourSearch3.png │ │ ├── AniCourSearchFull.png │ │ ├── Search.png │ │ └── SearchCropped.png │ └── SeasonViews │ │ ├── AniCourCompactSeason.jpg │ │ ├── AniCourGridViewSeason.png │ │ ├── AniCourGridViewSeason2.png │ │ ├── AniCourListViewSeason.png │ │ ├── AniCourSeasonsViews.png │ │ └── AniCourSeasonsViewsCropped.png └── transfer │ ├── ExportMyAnimeList.png │ └── ImportAniList.png ├── package-lock.json ├── package.json ├── release ├── app │ ├── package-lock.json │ └── package.json └── note.MD ├── src ├── __tests__ │ └── App.test.tsx ├── main │ ├── functions │ │ └── mainFunctions.ts │ ├── main.ts │ ├── menu.ts │ ├── preload.ts │ └── util.ts └── renderer │ ├── App.tsx │ ├── AppOld.tsx │ ├── IPC_notes.md │ ├── components │ ├── app │ │ ├── etc │ │ │ ├── ContextMenu.tsx │ │ │ ├── ContextMenuAlternative.tsx │ │ │ ├── ContextMenuNested.tsx │ │ │ ├── CustomTooltip1.tsx │ │ │ ├── CustomTooltipFixedWidth.tsx │ │ │ ├── DeleteModal.tsx │ │ │ ├── ErrorAPI.tsx │ │ │ ├── ErrorCredentials.tsx │ │ │ ├── ErrorNewsFetch.tsx │ │ │ ├── LoadingMessage.tsx │ │ │ ├── LoadingNews.tsx │ │ │ ├── MediaProgress.tsx │ │ │ ├── NextAiringEpisodeIndicator.tsx │ │ │ ├── ProgressBar.tsx │ │ │ ├── ProgressStepper.tsx │ │ │ ├── ProgressStepperManga.tsx │ │ │ ├── ProgressStepperVertical.tsx │ │ │ ├── ProgressVolumesStepper.tsx │ │ │ ├── ResetMenuApp.tsx │ │ │ ├── ScoreSelect.tsx │ │ │ ├── SvgIcons.tsx │ │ │ └── table │ │ │ │ ├── TableAverageScore.tsx │ │ │ │ ├── TableChapters.tsx │ │ │ │ ├── TableEpisodes.tsx │ │ │ │ ├── TableProgressChapterStepper.tsx │ │ │ │ ├── TableProgressStepper.tsx │ │ │ │ ├── TableProgressVolumeStepper.tsx │ │ │ │ ├── TableReleased.tsx │ │ │ │ ├── TableScore.tsx │ │ │ │ ├── TableSeason.tsx │ │ │ │ ├── TableStatus.tsx │ │ │ │ ├── TableTitleMain.tsx │ │ │ │ ├── TableTitleOther.tsx │ │ │ │ ├── TableType.tsx │ │ │ │ ├── TableVolumes.tsx │ │ │ │ └── TanstackTableRow.tsx │ │ ├── history │ │ │ ├── HistoryButton.tsx │ │ │ └── HistoryTab.tsx │ │ ├── main │ │ │ ├── Main.tsx │ │ │ ├── MainCategoryBar.tsx │ │ │ ├── MainFilterCategoryBar.tsx │ │ │ ├── MainTab.tsx │ │ │ ├── MainTabCompact.tsx │ │ │ ├── MainTabLi.tsx │ │ │ ├── MainTabList.tsx │ │ │ ├── MediaCard.tsx │ │ │ ├── MediaCardCompact.tsx │ │ │ ├── MediaDataGrid.tsx │ │ │ ├── MediaTableVirtuoso.tsx │ │ │ ├── cards │ │ │ │ └── MainSkeletonCards.tsx │ │ │ └── tables │ │ │ │ ├── MainMediaTable.tsx │ │ │ │ ├── MainTanstackTable.tsx │ │ │ │ ├── MediaMuiReactTable.tsx │ │ │ │ └── makeData.ts │ │ ├── news │ │ │ ├── NewsAdvanced.tsx │ │ │ ├── NewsAdvancedAnn.tsx │ │ │ ├── NewsBar.tsx │ │ │ ├── NewsButtons.tsx │ │ │ ├── NewsButtonsAdvanced.tsx │ │ │ ├── NewsCardANN.tsx │ │ │ ├── NewsCardMAL.tsx │ │ │ ├── NewsFullscreen.tsx │ │ │ ├── NewsPage.tsx │ │ │ ├── NewsRefresh.tsx │ │ │ ├── NewsTab.tsx │ │ │ └── NewsTabANN.tsx │ │ ├── search │ │ │ ├── FilterSelect.tsx │ │ │ ├── Search.tsx │ │ │ ├── SearchCategoryBar.tsx │ │ │ ├── SearchFilterCategoryBar.tsx │ │ │ ├── SearchMain.tsx │ │ │ ├── SearchMediaCard.tsx │ │ │ ├── SearchMediaCardCompact.tsx │ │ │ ├── SearchTab.tsx │ │ │ ├── SearchTabLi.tsx │ │ │ ├── SearchTabList.tsx │ │ │ └── tables │ │ │ │ ├── SearchMediaTable.tsx │ │ │ │ ├── SearchTanstackTable.tsx │ │ │ │ └── SearchTitleTableBox.tsx │ │ ├── seasons │ │ │ ├── SeasonCategoryBar.tsx │ │ │ ├── SeasonFilterCategoryBar.tsx │ │ │ ├── SeasonMain.tsx │ │ │ ├── SeasonMediaCard.tsx │ │ │ ├── SeasonMediaCardCompact.tsx │ │ │ ├── SeasonMenu.tsx │ │ │ ├── SeasonSearch.tsx │ │ │ ├── SeasonSearchDialog.tsx │ │ │ ├── SeasonTab.tsx │ │ │ ├── SeasonTabLi.tsx │ │ │ ├── SeasonTabList.tsx │ │ │ └── tables │ │ │ │ ├── SeasonMediaTable.tsx │ │ │ │ ├── SeasonTanstackTable.tsx │ │ │ │ └── SeasonTitleTableBox.tsx │ │ ├── sidebar │ │ │ ├── FeatureButtonGroup.tsx │ │ │ ├── FeatureButtonGroupNews.tsx │ │ │ ├── ListViewToggle.tsx │ │ │ ├── SideBar.tsx │ │ │ └── SortMenu.tsx │ │ ├── styled │ │ │ └── StyledComponents.tsx │ │ └── test │ │ │ ├── MediaProgress.tsx │ │ │ └── MediaTable.tsx │ ├── mediaAdvanced │ │ ├── AdvancedMain.tsx │ │ ├── AdvancedMainNOL.tsx │ │ ├── MediaAdvanced.tsx │ │ ├── description │ │ │ └── AdvancedDescription.tsx │ │ ├── entryInput │ │ │ ├── notOnList │ │ │ │ ├── AddToList.tsx │ │ │ │ └── EntryInputNotOnList.tsx │ │ │ └── onList │ │ │ │ ├── EntryInputOnList.tsx │ │ │ │ ├── JoyDatePicker.tsx │ │ │ │ ├── MyDatePicker.tsx │ │ │ │ ├── MyDatePickerCompletedAt.tsx │ │ │ │ ├── MyDatePickerStartedAt.tsx │ │ │ │ ├── NotesInput.tsx │ │ │ │ ├── PrivateCheckBox.tsx │ │ │ │ ├── PrivateCheckBoxAlt.tsx │ │ │ │ ├── ProgressInput.tsx │ │ │ │ ├── ProgressVolumesInput.tsx │ │ │ │ ├── RepeatInput.tsx │ │ │ │ ├── ScoreInput.tsx │ │ │ │ ├── StatusSelect.tsx │ │ │ │ └── UpdateButton.tsx │ │ ├── extra │ │ │ ├── AdvancedExtra.tsx │ │ │ ├── AdvancedExtraSelect.tsx │ │ │ ├── AlternativeLink.tsx │ │ │ ├── DeleteButton.tsx │ │ │ ├── InfoButton.tsx │ │ │ ├── ThemeSongButton.tsx │ │ │ └── TrailerButton.tsx │ │ ├── image │ │ │ └── AdvancedImage.tsx │ │ ├── information │ │ │ ├── AdvancedInformation.tsx │ │ │ ├── AdvancedInformationDefault.tsx │ │ │ ├── AdvancedInformationDelete.tsx │ │ │ ├── AdvancedInformationThemes.tsx │ │ │ ├── AdvancedInformationTitles.tsx │ │ │ ├── AdvancedInformationTrailer.tsx │ │ │ ├── AdvancedMediaAverageScore.tsx │ │ │ ├── AdvancedMediaGenres.tsx │ │ │ ├── AdvancedMediaSeason.tsx │ │ │ ├── AdvancedMediaStatus.tsx │ │ │ ├── AdvancedMediaStudio.tsx │ │ │ ├── AdvancedMediaSynonyms.tsx │ │ │ ├── AdvancedMediaThemes.tsx │ │ │ └── AdvancedMediaType.tsx │ │ └── title │ │ │ └── AdvancedTitle.tsx │ ├── settings │ │ ├── Settings.tsx │ │ ├── SettingsMain.tsx │ │ ├── TestButton.tsx │ │ ├── about │ │ │ └── AboutSection.tsx │ │ ├── app │ │ │ ├── AdultLabel.tsx │ │ │ ├── DefaultStatus.tsx │ │ │ ├── NextAiringEpisodeMainList.tsx │ │ │ ├── SelectDefaultLink.tsx │ │ │ ├── SelectDefaultSeasonsSort.tsx │ │ │ ├── SelectDefaultView.tsx │ │ │ └── SelectSeasonChange.tsx │ │ ├── etc │ │ │ ├── CardContentPaddingAdjusted.tsx │ │ │ ├── CustomSettingsTooltip.tsx │ │ │ ├── SaveButton.tsx │ │ │ └── SubmitButton.tsx │ │ ├── lang │ │ │ └── SelectLanguage.tsx │ │ ├── reset │ │ │ └── ResetButton.tsx │ │ ├── services │ │ │ ├── AccountSection.tsx │ │ │ ├── ResetLoginButton.tsx │ │ │ ├── SelectList.tsx │ │ │ ├── SelectNews.tsx │ │ │ ├── TokenButton.tsx │ │ │ ├── TokenInput.tsx │ │ │ └── UsernameInput.tsx │ │ └── theme │ │ │ ├── SelectTheme.tsx │ │ │ └── ThemeToggle.tsx │ └── trailer │ │ ├── MyTrailer.tsx │ │ ├── TrailerAvailablePage.tsx │ │ ├── TrailerNotAvailablePage.tsx │ │ └── TrailerPage.tsx │ ├── context │ ├── AdultContext.tsx │ ├── CategoryContext.tsx │ ├── CategoryCountContext.tsx │ ├── CategoryLastContext.tsx │ ├── DefaultViewContext.tsx │ ├── FilterContext.tsx │ ├── FilteredListContext.tsx │ ├── ListServiceTypeContext.tsx │ ├── MainContext.tsx │ ├── MainListContext.tsx │ ├── MainViewContext.tsx │ ├── NewsAdvContext.tsx │ ├── NewsAnnContext.tsx │ ├── NewsContext.tsx │ ├── NewsInfoContext.tsx │ ├── NewsServiceTypeContext.tsx │ ├── SearchContext.tsx │ ├── SearchTermContext.tsx │ ├── SeasonInputContext.tsx │ ├── SeasonsContext.tsx │ ├── SidebarContext.tsx │ ├── SortContext.tsx │ ├── SortLastContext.tsx │ ├── ThemeContext.tsx │ ├── TitleContext.tsx │ ├── advanced │ │ ├── AdvancedDefaultLinkContext.tsx │ │ ├── AdvancedInputContext.tsx │ │ ├── AdvancedMediaContext.tsx │ │ ├── AdvancedMoreInfoContext.tsx │ │ └── AdvancedThemeSongContext.tsx │ ├── menu │ │ ├── MenuDataContext.tsx │ │ ├── PosXContext.tsx │ │ ├── PosYContext.tsx │ │ └── ShowMenuContext.tsx │ └── services │ │ ├── AniListTokenContext.tsx │ │ ├── AniListUsernameContext.tsx │ │ ├── MyAnimeListContext.tsx │ │ └── MyAnimeListTokenContext.tsx │ ├── extra │ ├── AniListAllTags.json │ └── AniListGenres.json │ ├── functions │ ├── AnimeThemeSongs.ts │ ├── CheckForListFlags.ts │ ├── LocationFunctions.tsx │ ├── MainMediaListFunctions.tsx │ ├── NewsFunctions.tsx │ ├── SearchFunctions.tsx │ ├── SeasonsFunctions.tsx │ ├── StatusFunction.tsx │ ├── TestSettingsFunction.tsx │ ├── UserFunctions.ts │ ├── api │ │ ├── mutations │ │ │ ├── addEntry.tsx │ │ │ ├── deleteEntry.tsx │ │ │ └── updateEntry.tsx │ │ ├── queries │ │ │ └── themeSongQuery.ts │ │ └── queue │ │ │ └── QueueMutationsFunctions.tsx │ ├── colors │ │ └── colorFunctions.ts │ ├── data │ │ ├── generator │ │ │ └── createMediaListEntryData.tsx │ │ ├── update │ │ │ ├── mainMediaList.tsx │ │ │ ├── searchList.tsx │ │ │ ├── seasonsList.tsx │ │ │ └── updateQueryClientLists.tsx │ │ └── validation │ │ │ └── ValidationFunctions.tsx │ ├── edit │ │ ├── adjustedLocationStatus.tsx │ │ ├── componentTypes.ts │ │ ├── createMediaListEntry.tsx │ │ ├── findMedia.tsx │ │ ├── formatInfo.ts │ │ ├── getAdjustedSiteLink.tsx │ │ └── getSortValues.ts │ ├── input │ │ ├── InputFunctions.tsx │ │ └── LimitInputFunctions.tsx │ ├── sort │ │ ├── sortFunctions.ts │ │ ├── sortMainFunctions.ts │ │ ├── sortSearchFunctions.ts │ │ └── sortSeasonsFunctions.ts │ └── view │ │ ├── CountFunctions.tsx │ │ ├── DataTableFunctions.tsx │ │ ├── FilterFunctions.tsx │ │ ├── InfoViewFunctions.tsx │ │ ├── MainViewFunctions.tsx │ │ ├── SearchViewFunctions.tsx │ │ ├── SeasonViewFunctions.tsx │ │ └── TitlePreferenceFunctions.tsx │ ├── index.ejs │ ├── index.tsx │ ├── preload.d.ts │ ├── store.ts │ └── styles │ ├── App.scss │ ├── MediaAdvanced.scss │ ├── NewsAdvanced.scss │ ├── Trailer.scss │ └── tables.scss └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | -------------------------------------------------------------------------------- /.erb/configs/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": "off", 4 | "global-require": "off", 5 | "import/no-dynamic-require": "off" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.base.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Base webpack config used across other specific configs 3 | */ 4 | 5 | import webpack from 'webpack'; 6 | import TsconfigPathsPlugins from 'tsconfig-paths-webpack-plugin'; 7 | import webpackPaths from './webpack.paths'; 8 | import { dependencies as externals } from '../../release/app/package.json'; 9 | 10 | const configuration: webpack.Configuration = { 11 | externals: [...Object.keys(externals || {})], 12 | 13 | stats: 'errors-only', 14 | 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.[jt]sx?$/, 19 | exclude: /node_modules/, 20 | use: { 21 | loader: 'ts-loader', 22 | options: { 23 | // Remove this line to enable type checking in webpack builds 24 | transpileOnly: true, 25 | compilerOptions: { 26 | module: 'esnext', 27 | }, 28 | }, 29 | }, 30 | }, 31 | ], 32 | }, 33 | 34 | output: { 35 | path: webpackPaths.srcPath, 36 | // https://github.com/webpack/webpack/issues/1114 37 | library: { 38 | type: 'commonjs2', 39 | }, 40 | }, 41 | 42 | /** 43 | * Determine the array of extensions that should be used to resolve modules. 44 | */ 45 | resolve: { 46 | extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'], 47 | modules: [webpackPaths.srcPath, 'node_modules'], 48 | // There is no need to add aliases here, the paths in tsconfig get mirrored 49 | plugins: [new TsconfigPathsPlugins()], 50 | }, 51 | 52 | plugins: [ 53 | new webpack.EnvironmentPlugin({ 54 | NODE_ENV: 'production', 55 | }), 56 | ], 57 | }; 58 | 59 | export default configuration; 60 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.eslint.ts: -------------------------------------------------------------------------------- 1 | /* eslint import/no-unresolved: off, import/no-self-import: off */ 2 | 3 | module.exports = require('./webpack.config.renderer.dev').default; 4 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.preload.dev.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import webpack from 'webpack'; 3 | import { merge } from 'webpack-merge'; 4 | import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; 5 | import baseConfig from './webpack.config.base'; 6 | import webpackPaths from './webpack.paths'; 7 | import checkNodeEnv from '../scripts/check-node-env'; 8 | 9 | // When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's 10 | // at the dev webpack config is not accidentally run in a production environment 11 | if (process.env.NODE_ENV === 'production') { 12 | checkNodeEnv('development'); 13 | } 14 | 15 | const configuration: webpack.Configuration = { 16 | devtool: 'inline-source-map', 17 | 18 | mode: 'development', 19 | 20 | target: 'electron-preload', 21 | 22 | entry: path.join(webpackPaths.srcMainPath, 'preload.ts'), 23 | 24 | output: { 25 | path: webpackPaths.dllPath, 26 | filename: 'preload.js', 27 | library: { 28 | type: 'umd', 29 | }, 30 | }, 31 | 32 | plugins: [ 33 | new BundleAnalyzerPlugin({ 34 | analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled', 35 | }), 36 | 37 | /** 38 | * Create global constants which can be configured at compile time. 39 | * 40 | * Useful for allowing different behaviour between development builds and 41 | * release builds 42 | * 43 | * NODE_ENV should be production so that modules do not perform certain 44 | * development checks 45 | * 46 | * By default, use 'development' as NODE_ENV. This can be overriden with 47 | * 'staging', for example, by changing the ENV variables in the npm scripts 48 | */ 49 | new webpack.EnvironmentPlugin({ 50 | NODE_ENV: 'development', 51 | }), 52 | 53 | new webpack.LoaderOptionsPlugin({ 54 | debug: true, 55 | }), 56 | ], 57 | 58 | /** 59 | * Disables webpack processing of __dirname and __filename. 60 | * If you run the bundle in node.js it falls back to these values of node.js. 61 | * https://github.com/webpack/webpack/issues/2010 62 | */ 63 | node: { 64 | __dirname: false, 65 | __filename: false, 66 | }, 67 | 68 | watch: true, 69 | }; 70 | 71 | export default merge(baseConfig, configuration); 72 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.renderer.dev.dll.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds the DLL for development electron renderer process 3 | */ 4 | 5 | import webpack from 'webpack'; 6 | import path from 'path'; 7 | import { merge } from 'webpack-merge'; 8 | import baseConfig from './webpack.config.base'; 9 | import webpackPaths from './webpack.paths'; 10 | import { dependencies } from '../../package.json'; 11 | import checkNodeEnv from '../scripts/check-node-env'; 12 | 13 | checkNodeEnv('development'); 14 | 15 | const dist = webpackPaths.dllPath; 16 | 17 | const configuration: webpack.Configuration = { 18 | context: webpackPaths.rootPath, 19 | 20 | devtool: 'eval', 21 | 22 | mode: 'development', 23 | 24 | target: 'electron-renderer', 25 | 26 | externals: ['fsevents', 'crypto-browserify'], 27 | 28 | /** 29 | * Use `module` from `webpack.config.renderer.dev.js` 30 | */ 31 | module: require('./webpack.config.renderer.dev').default.module, 32 | 33 | entry: { 34 | renderer: Object.keys(dependencies || {}), 35 | }, 36 | 37 | output: { 38 | path: dist, 39 | filename: '[name].dev.dll.js', 40 | library: { 41 | name: 'renderer', 42 | type: 'var', 43 | }, 44 | }, 45 | 46 | plugins: [ 47 | new webpack.DllPlugin({ 48 | path: path.join(dist, '[name].json'), 49 | name: '[name]', 50 | }), 51 | 52 | /** 53 | * Create global constants which can be configured at compile time. 54 | * 55 | * Useful for allowing different behaviour between development builds and 56 | * release builds 57 | * 58 | * NODE_ENV should be production so that modules do not perform certain 59 | * development checks 60 | */ 61 | new webpack.EnvironmentPlugin({ 62 | NODE_ENV: 'development', 63 | }), 64 | 65 | new webpack.LoaderOptionsPlugin({ 66 | debug: true, 67 | options: { 68 | context: webpackPaths.srcPath, 69 | output: { 70 | path: webpackPaths.dllPath, 71 | }, 72 | }, 73 | }), 74 | ], 75 | }; 76 | 77 | export default merge(baseConfig, configuration); 78 | -------------------------------------------------------------------------------- /.erb/configs/webpack.paths.ts: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const rootPath = path.join(__dirname, '../..'); 4 | 5 | const dllPath = path.join(__dirname, '../dll'); 6 | 7 | const srcPath = path.join(rootPath, 'src'); 8 | const srcMainPath = path.join(srcPath, 'main'); 9 | const srcRendererPath = path.join(srcPath, 'renderer'); 10 | 11 | const releasePath = path.join(rootPath, 'release'); 12 | const appPath = path.join(releasePath, 'app'); 13 | const appPackagePath = path.join(appPath, 'package.json'); 14 | const appNodeModulesPath = path.join(appPath, 'node_modules'); 15 | const srcNodeModulesPath = path.join(srcPath, 'node_modules'); 16 | 17 | const distPath = path.join(appPath, 'dist'); 18 | const distMainPath = path.join(distPath, 'main'); 19 | const distRendererPath = path.join(distPath, 'renderer'); 20 | 21 | const buildPath = path.join(releasePath, 'build'); 22 | 23 | export default { 24 | rootPath, 25 | dllPath, 26 | srcPath, 27 | srcMainPath, 28 | srcRendererPath, 29 | releasePath, 30 | appPath, 31 | appPackagePath, 32 | appNodeModulesPath, 33 | srcNodeModulesPath, 34 | distPath, 35 | distMainPath, 36 | distRendererPath, 37 | buildPath, 38 | }; 39 | -------------------------------------------------------------------------------- /.erb/img/erb-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/.erb/img/erb-logo.png -------------------------------------------------------------------------------- /.erb/mocks/fileMock.js: -------------------------------------------------------------------------------- 1 | export default 'test-file-stub'; 2 | -------------------------------------------------------------------------------- /.erb/note.MD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/.erb/note.MD -------------------------------------------------------------------------------- /.erb/scripts/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": "off", 4 | "global-require": "off", 5 | "import/no-dynamic-require": "off", 6 | "import/no-extraneous-dependencies": "off" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.erb/scripts/check-build-exists.ts: -------------------------------------------------------------------------------- 1 | // Check if the renderer and main bundles are built 2 | import path from 'path'; 3 | import chalk from 'chalk'; 4 | import fs from 'fs'; 5 | import webpackPaths from '../configs/webpack.paths'; 6 | 7 | const mainPath = path.join(webpackPaths.distMainPath, 'main.js'); 8 | const rendererPath = path.join(webpackPaths.distRendererPath, 'renderer.js'); 9 | 10 | if (!fs.existsSync(mainPath)) { 11 | throw new Error( 12 | chalk.whiteBright.bgRed.bold( 13 | 'The main process is not built yet. Build it by running "npm run build:main"', 14 | ), 15 | ); 16 | } 17 | 18 | if (!fs.existsSync(rendererPath)) { 19 | throw new Error( 20 | chalk.whiteBright.bgRed.bold( 21 | 'The renderer process is not built yet. Build it by running "npm run build:renderer"', 22 | ), 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /.erb/scripts/check-native-dep.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import chalk from 'chalk'; 3 | import { execSync } from 'child_process'; 4 | import { dependencies } from '../../package.json'; 5 | 6 | if (dependencies) { 7 | const dependenciesKeys = Object.keys(dependencies); 8 | const nativeDeps = fs 9 | .readdirSync('node_modules') 10 | .filter((folder) => fs.existsSync(`node_modules/${folder}/binding.gyp`)); 11 | if (nativeDeps.length === 0) { 12 | process.exit(0); 13 | } 14 | try { 15 | // Find the reason for why the dependency is installed. If it is installed 16 | // because of a devDependency then that is okay. Warn when it is installed 17 | // because of a dependency 18 | const { dependencies: dependenciesObject } = JSON.parse( 19 | execSync(`npm ls ${nativeDeps.join(' ')} --json`).toString(), 20 | ); 21 | const rootDependencies = Object.keys(dependenciesObject); 22 | const filteredRootDependencies = rootDependencies.filter((rootDependency) => 23 | dependenciesKeys.includes(rootDependency), 24 | ); 25 | if (filteredRootDependencies.length > 0) { 26 | const plural = filteredRootDependencies.length > 1; 27 | console.log(` 28 | ${chalk.whiteBright.bgYellow.bold( 29 | 'Webpack does not work with native dependencies.', 30 | )} 31 | ${chalk.bold(filteredRootDependencies.join(', '))} ${ 32 | plural ? 'are native dependencies' : 'is a native dependency' 33 | } and should be installed inside of the "./release/app" folder. 34 | First, uninstall the packages from "./package.json": 35 | ${chalk.whiteBright.bgGreen.bold('npm uninstall your-package')} 36 | ${chalk.bold( 37 | 'Then, instead of installing the package to the root "./package.json":', 38 | )} 39 | ${chalk.whiteBright.bgRed.bold('npm install your-package')} 40 | ${chalk.bold('Install the package to "./release/app/package.json"')} 41 | ${chalk.whiteBright.bgGreen.bold( 42 | 'cd ./release/app && npm install your-package', 43 | )} 44 | Read more about native dependencies at: 45 | ${chalk.bold( 46 | 'https://electron-react-boilerplate.js.org/docs/adding-dependencies/#module-structure', 47 | )} 48 | `); 49 | process.exit(1); 50 | } 51 | } catch (e) { 52 | console.log('Native dependencies could not be checked'); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.erb/scripts/check-node-env.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | 3 | export default function checkNodeEnv(expectedEnv) { 4 | if (!expectedEnv) { 5 | throw new Error('"expectedEnv" not set'); 6 | } 7 | 8 | if (process.env.NODE_ENV !== expectedEnv) { 9 | console.log( 10 | chalk.whiteBright.bgRed.bold( 11 | `"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config`, 12 | ), 13 | ); 14 | process.exit(2); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.erb/scripts/check-port-in-use.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | import detectPort from 'detect-port'; 3 | 4 | const port = process.env.PORT || '1212'; 5 | 6 | detectPort(port, (_err, availablePort) => { 7 | if (port !== String(availablePort)) { 8 | throw new Error( 9 | chalk.whiteBright.bgRed.bold( 10 | `Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 npm start`, 11 | ), 12 | ); 13 | } else { 14 | process.exit(0); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /.erb/scripts/clean.js: -------------------------------------------------------------------------------- 1 | import { rimrafSync } from 'rimraf'; 2 | import fs from 'fs'; 3 | import webpackPaths from '../configs/webpack.paths'; 4 | 5 | const foldersToRemove = [ 6 | webpackPaths.distPath, 7 | webpackPaths.buildPath, 8 | webpackPaths.dllPath, 9 | ]; 10 | 11 | foldersToRemove.forEach((folder) => { 12 | if (fs.existsSync(folder)) rimrafSync(folder); 13 | }); 14 | -------------------------------------------------------------------------------- /.erb/scripts/delete-source-maps.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { rimrafSync } from 'rimraf'; 4 | import webpackPaths from '../configs/webpack.paths'; 5 | 6 | export default function deleteSourceMaps() { 7 | if (fs.existsSync(webpackPaths.distMainPath)) 8 | rimrafSync(path.join(webpackPaths.distMainPath, '*.js.map'), { 9 | glob: true, 10 | }); 11 | if (fs.existsSync(webpackPaths.distRendererPath)) 12 | rimrafSync(path.join(webpackPaths.distRendererPath, '*.js.map'), { 13 | glob: true, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /.erb/scripts/electron-rebuild.js: -------------------------------------------------------------------------------- 1 | import { execSync } from 'child_process'; 2 | import fs from 'fs'; 3 | import { dependencies } from '../../release/app/package.json'; 4 | import webpackPaths from '../configs/webpack.paths'; 5 | 6 | if ( 7 | Object.keys(dependencies || {}).length > 0 && 8 | fs.existsSync(webpackPaths.appNodeModulesPath) 9 | ) { 10 | const electronRebuildCmd = 11 | '../../node_modules/.bin/electron-rebuild --force --types prod,dev,optional --module-dir .'; 12 | const cmd = 13 | process.platform === 'win32' 14 | ? electronRebuildCmd.replace(/\//g, '\\') 15 | : electronRebuildCmd; 16 | execSync(cmd, { 17 | cwd: webpackPaths.appPath, 18 | stdio: 'inherit', 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /.erb/scripts/link-modules.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import webpackPaths from '../configs/webpack.paths'; 3 | 4 | const { srcNodeModulesPath } = webpackPaths; 5 | const { appNodeModulesPath } = webpackPaths; 6 | 7 | if (!fs.existsSync(srcNodeModulesPath) && fs.existsSync(appNodeModulesPath)) { 8 | fs.symlinkSync(appNodeModulesPath, srcNodeModulesPath, 'junction'); 9 | } 10 | -------------------------------------------------------------------------------- /.erb/scripts/notarize.js: -------------------------------------------------------------------------------- 1 | const { notarize } = require('@electron/notarize'); 2 | const { build } = require('../../package.json'); 3 | 4 | exports.default = async function notarizeMacos(context) { 5 | const { electronPlatformName, appOutDir } = context; 6 | if (electronPlatformName !== 'darwin') { 7 | return; 8 | } 9 | 10 | if (process.env.CI !== 'true') { 11 | console.warn('Skipping notarizing step. Packaging is not running in CI'); 12 | return; 13 | } 14 | 15 | if ( 16 | !('APPLE_ID' in process.env && 'APPLE_APP_SPECIFIC_PASSWORD' in process.env) 17 | ) { 18 | console.warn( 19 | 'Skipping notarizing step. APPLE_ID and APPLE_APP_SPECIFIC_PASSWORD env variables must be set', 20 | ); 21 | return; 22 | } 23 | 24 | const appName = context.packager.appInfo.productFilename; 25 | 26 | await notarize({ 27 | appBundleId: build.appId, 28 | appPath: `${appOutDir}/${appName}.app`, 29 | appleId: process.env.APPLE_ID, 30 | appleIdPassword: process.env.APPLE_APP_SPECIFIC_PASSWORD, 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | .eslintcache 13 | 14 | # Dependency directory 15 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 16 | node_modules 17 | 18 | # OSX 19 | .DS_Store 20 | 21 | release/app/dist 22 | release/build 23 | .erb/dll 24 | 25 | .idea 26 | npm-debug.log.* 27 | *.css.d.ts 28 | *.sass.d.ts 29 | *.scss.d.ts 30 | 31 | # eslint ignores hidden directories by default: 32 | # https://github.com/eslint/eslint/issues/8429 33 | !.erb 34 | 35 | # test 36 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'erb', 3 | plugins: ['@typescript-eslint'], 4 | rules: { 5 | // A temporary hack related to IDE not resolving correct package.json 6 | 'import/no-extraneous-dependencies': 'off', 7 | 'react/react-in-jsx-scope': 'off', 8 | 'react/jsx-filename-extension': 'off', 9 | 'import/extensions': 'off', 10 | 'import/no-unresolved': 'off', 11 | 'import/no-import-module-exports': 'off', 12 | 'no-shadow': 'off', 13 | '@typescript-eslint/no-shadow': 'error', 14 | 'no-unused-vars': 'off', 15 | '@typescript-eslint/no-unused-vars': 'warn', 16 | 'react/jsx-no-useless-fragment': 'off', 17 | 'react/function-component-definition': 'off', 18 | 'react/jsx-no-constructed-context-values': 'off', 19 | 'react/no-unstable-nested-components': 'off', 20 | camelcase: 'off', 21 | }, 22 | parserOptions: { 23 | ecmaVersion: 2022, 24 | sourceType: 'module', 25 | }, 26 | settings: { 27 | 'import/resolver': { 28 | // See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below 29 | node: { 30 | extensions: ['.js', '.jsx', '.ts', '.tsx'], 31 | moduleDirectory: ['node_modules', 'src/'], 32 | }, 33 | webpack: { 34 | config: require.resolve('./.erb/configs/webpack.config.eslint.ts'), 35 | }, 36 | typescript: {}, 37 | }, 38 | 'import/parsers': { 39 | '@typescript-eslint/parser': ['.ts', '.tsx'], 40 | }, 41 | }, 42 | }; 43 | // test 44 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.exe binary 3 | *.png binary 4 | *.jpg binary 5 | *.jpeg binary 6 | *.ico binary 7 | *.icns binary 8 | *.eot binary 9 | *.otf binary 10 | *.ttf binary 11 | *.woff binary 12 | *.woff2 binary 13 | # test 14 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ReStartQ] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: ReStartQ 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 15 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | requiredHeaders: 2 | - Prerequisites 3 | - Expected Behavior 4 | - Current Behavior 5 | - Possible Solution 6 | - Your Environment 7 | -------------------------------------------------------------------------------- /.github/note.MD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/.github/note.MD -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | publish: 10 | # To enable auto publishing to github, update your electron publisher 11 | # config in package.json > "build" and remove the conditional below 12 | if: ${{ github.repository_owner == 'electron-react-boilerplate' }} 13 | 14 | runs-on: ${{ matrix.os }} 15 | 16 | strategy: 17 | matrix: 18 | os: [macos-latest] 19 | 20 | steps: 21 | - name: Checkout git repo 22 | uses: actions/checkout@v3 23 | 24 | - name: Install Node and NPM 25 | uses: actions/setup-node@v3 26 | with: 27 | node-version: 18 28 | cache: npm 29 | 30 | - name: Install and build 31 | run: | 32 | npm install 33 | npm run postinstall 34 | npm run build 35 | 36 | - name: Publish releases 37 | env: 38 | # These values are used for auto updates signing 39 | APPLE_ID: ${{ secrets.APPLE_ID }} 40 | APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASS }} 41 | CSC_LINK: ${{ secrets.CSC_LINK }} 42 | CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} 43 | # This is used for uploading release assets to github 44 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | run: | 46 | npm exec electron-builder -- --publish always --win --mac --linux 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | .eslintcache 13 | 14 | # Dependency directory 15 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 16 | node_modules 17 | 18 | # OSX 19 | .DS_Store 20 | 21 | release/app/dist 22 | release/build 23 | .erb/dll 24 | 25 | .idea 26 | npm-debug.log.* 27 | *.css.d.ts 28 | *.sass.d.ts 29 | *.scss.d.ts 30 | # test 31 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["dbaeumer.vscode-eslint", "EditorConfig.EditorConfig"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Electron: Main", 6 | "type": "node", 7 | "request": "launch", 8 | "protocol": "inspector", 9 | "runtimeExecutable": "npm", 10 | "runtimeArgs": ["run", "start"], 11 | "env": { 12 | "MAIN_ARGS": "--inspect=5858 --remote-debugging-port=9223" 13 | } 14 | }, 15 | { 16 | "name": "Electron: Renderer", 17 | "type": "chrome", 18 | "request": "attach", 19 | "port": 9223, 20 | "webRoot": "${workspaceFolder}", 21 | "timeout": 15000 22 | } 23 | ], 24 | "compounds": [ 25 | { 26 | "name": "Electron: All", 27 | "configurations": ["Electron: Main", "Electron: Renderer"] 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /.vscode/note.MD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/.vscode/note.MD -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | ".eslintrc": "jsonc", 4 | ".prettierrc": "jsonc", 5 | ".eslintignore": "ignore" 6 | }, 7 | 8 | "eslint.validate": [ 9 | "javascript", 10 | "javascriptreact", 11 | "html", 12 | "typescriptreact" 13 | ], 14 | 15 | "javascript.validate.enable": false, 16 | "javascript.format.enable": false, 17 | "typescript.format.enable": false, 18 | 19 | "search.exclude": { 20 | ".git": true, 21 | ".eslintcache": true, 22 | ".erb/dll": true, 23 | "release/{build,app/dist}": true, 24 | "node_modules": true, 25 | "npm-debug.log.*": true, 26 | "test/**/__snapshots__": true, 27 | "package-lock.json": true, 28 | "*.{css,sass,scss}.d.ts": true 29 | }, 30 | "editor.formatOnSave": true, 31 | "workbench.colorCustomizations": { 32 | "terminal.background": "#161B1D", 33 | "terminal.foreground": "#7EA2B4", 34 | "terminalCursor.background": "#7EA2B4", 35 | "terminalCursor.foreground": "#7EA2B4", 36 | "terminal.ansiBlack": "#161B1D", 37 | "terminal.ansiBlue": "#257FAD", 38 | "terminal.ansiBrightBlack": "#5A7B8C", 39 | "terminal.ansiBrightBlue": "#257FAD", 40 | "terminal.ansiBrightCyan": "#2D8F6F", 41 | "terminal.ansiBrightGreen": "#568C3B", 42 | "terminal.ansiBrightMagenta": "#6B6BB8", 43 | "terminal.ansiBrightRed": "#D22D72", 44 | "terminal.ansiBrightWhite": "#EBF8FF", 45 | "terminal.ansiBrightYellow": "#8A8A0F", 46 | "terminal.ansiCyan": "#2D8F6F", 47 | "terminal.ansiGreen": "#568C3B", 48 | "terminal.ansiMagenta": "#6B6BB8", 49 | "terminal.ansiRed": "#D22D72", 50 | "terminal.ansiWhite": "#7EA2B4", 51 | "terminal.ansiYellow": "#8A8A0F" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /assets/Attributions.md: -------------------------------------------------------------------------------- 1 | Gear icons created by Freepik - Flaticon 2 | Lightweight icon by Icons8 -------------------------------------------------------------------------------- /assets/assets.d.ts: -------------------------------------------------------------------------------- 1 | type Styles = Record; 2 | 3 | declare module '*.svg' { 4 | const content: string; 5 | export default content; 6 | } 7 | 8 | declare module '*.png' { 9 | const content: string; 10 | export default content; 11 | } 12 | 13 | declare module '*.jpg' { 14 | const content: string; 15 | export default content; 16 | } 17 | 18 | declare module '*.scss' { 19 | const content: Styles; 20 | export default content; 21 | } 22 | 23 | declare module '*.sass' { 24 | const content: Styles; 25 | export default content; 26 | } 27 | 28 | declare module '*.css' { 29 | const content: Styles; 30 | export default content; 31 | } 32 | -------------------------------------------------------------------------------- /assets/entitlements.mac.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-unsigned-executable-memory 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /assets/gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/gear.png -------------------------------------------------------------------------------- /assets/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icon.icns -------------------------------------------------------------------------------- /assets/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icon.ico -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icon.png -------------------------------------------------------------------------------- /assets/icons/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/1024x1024.png -------------------------------------------------------------------------------- /assets/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/128x128.png -------------------------------------------------------------------------------- /assets/icons/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/16x16.png -------------------------------------------------------------------------------- /assets/icons/24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/24x24.png -------------------------------------------------------------------------------- /assets/icons/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/256x256.png -------------------------------------------------------------------------------- /assets/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/32x32.png -------------------------------------------------------------------------------- /assets/icons/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/48x48.png -------------------------------------------------------------------------------- /assets/icons/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/512x512.png -------------------------------------------------------------------------------- /assets/icons/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/64x64.png -------------------------------------------------------------------------------- /assets/icons/96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/icons/96x96.png -------------------------------------------------------------------------------- /assets/lightweight-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/lightweight-48.png -------------------------------------------------------------------------------- /assets/note.MD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/note.MD -------------------------------------------------------------------------------- /assets/restore-window-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/restore-window-64.png -------------------------------------------------------------------------------- /assets/restore-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/restore-window.png -------------------------------------------------------------------------------- /assets/settings-gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/assets/settings-gear.png -------------------------------------------------------------------------------- /help/FAQ.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/help/FAQ.md -------------------------------------------------------------------------------- /help/FilterAndSortList.md: -------------------------------------------------------------------------------- 1 | # Filter by list: 2 | 3 | Advanced filtering is now available, you can now select what property on the list that you want to filter for.
4 | By default, it is set everything on this list is filtered.
5 | Advanced filtering helps with avoiding crossovers between media properties such as:
6 | Ex: Studio/Producer: TV Tokyo and Type: TV
7 | **The following is a list of what you can filter by** 8 | 9 | - All (All the properties below are filtered for, this is the default state and is set when you first enter the app) 10 | - Titles (Romaji, English, Native, and synonyms) 11 | - Tags 12 | - Genres 13 | - Studios/Producers 14 | - Seasons (can be the season, year or both) 15 | - Status 16 | - Source 17 | - Type 18 | ## Advanced Filtering 19 | Here is an image of how to use select a property to filter by. 20 |

Hello

21 | 22 | # Sort by list: 23 | 24 | ## Anime List 25 | 26 | - Status 27 | - Title 28 | - Episode Progress 29 | - Score 30 | - Type 31 | - Season 32 | 33 | ## Manga List / Light Novel List 34 | 35 | - Status 36 | - Title 37 | - Chapter Progress 38 | - Volume Progress 39 | - Score 40 | - Season 41 | 42 | ## Search 43 | 44 | ### Anime 45 | 46 | - Status 47 | - Title 48 | - Episodes 49 | - Score 50 | - Type 51 | - Season 52 | 53 | ### Manga / Light Novel 54 | 55 | - Status 56 | - Title 57 | - Chapters 58 | - Volumes 59 | - Score 60 | - Season 61 | 62 | ## Seasons 63 | 64 | - Next Airing Time 65 | - Status 66 | - Title 67 | - Episodes 68 | - Score 69 | - Popularity 70 | -------------------------------------------------------------------------------- /help/InstallHelp.md: -------------------------------------------------------------------------------- 1 | ## Download and Installation 2 | 3 | **_Whenever you get a warning message in the browser, you will have to allow for the download with an alternate option that may show up as something like "download suspicious file" (chrome) or "keep file" (edge)._** 4 | 5 | You can download the app [here](https://github.com/ReStartQ/AniCour/releases). 6 | 7 | 1. Download the setup file from the latest release and install it on your computer. 8 | 2. The setup file is labeled as AniCour-Setup-x.x.x.exe, where x denotes a number for the version. 9 | **Ex: AniCour-Setup-1.7.0.exe** 10 | 3. When you run the exe file, Windows will give a message like below, click on "More info"

11 | 4. A new option will appear, "Run anyway". Click on it.

12 | 5. The installer menu will open up to allow you to install it on your computer.

13 | 6. Connect your AniList account to the app and use the app to track, search, and manage your anime, manga, and light novels. 14 | **Need help connecting your AniList account to AniCour? Instructions are [here](https://github.com/ReStartQ/anicour/blob/main/help/Setup.md).** 15 | -------------------------------------------------------------------------------- /help/MyAnimeListToAniListTransfer.md: -------------------------------------------------------------------------------- 1 | # Transfering anime/manga lists from MyAnimeList to AniList 2 | 3 | 1) Transfering your lists from MyAnimeList to AniList requires the export of your xml file from MyAnimeList.
4 | 2) To export your xml file, use MyAnimeList's [export service](http://myanimelist.net/panel.php?go=export). 5 | 6 | ![exportMyAnimeList](https://github.com/ReStartQ/anicour/blob/main/images/transfer/ExportMyAnimeList.png) 7 | 8 | 3) The file will be compressed, so you will need to extract it with an extracting tool such as winzip, winrar, etc. 9 | 4) To import it to AniList, use the import feature on the website's settings page. 10 | 11 | ![importAniList](https://github.com/ReStartQ/anicour/blob/main/images/transfer/ImportAniList.png) 12 | -------------------------------------------------------------------------------- /help/Other.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/help/Other.md -------------------------------------------------------------------------------- /help/Updates.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/help/Updates.md -------------------------------------------------------------------------------- /images/banner/AniCour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/banner/AniCour.png -------------------------------------------------------------------------------- /images/banner/AniCourBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/banner/AniCourBanner.png -------------------------------------------------------------------------------- /images/banner/AniCourBannerWide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/banner/AniCourBannerWide.png -------------------------------------------------------------------------------- /images/banner/AniCourSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/banner/AniCourSmall.png -------------------------------------------------------------------------------- /images/help/AniCourAdvancedFiltering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourAdvancedFiltering.png -------------------------------------------------------------------------------- /images/help/AniCourInstallationMenu1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourInstallationMenu1.png -------------------------------------------------------------------------------- /images/help/AniCourInstallationMenu2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourInstallationMenu2.png -------------------------------------------------------------------------------- /images/help/AniCourNoCodeSigning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourNoCodeSigning.png -------------------------------------------------------------------------------- /images/help/AniCourNoCodeSigningInitial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourNoCodeSigningInitial.png -------------------------------------------------------------------------------- /images/help/AniCourSaveInformation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourSaveInformation.png -------------------------------------------------------------------------------- /images/help/AniCourSettingsButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourSettingsButton.png -------------------------------------------------------------------------------- /images/help/AniCourSettingsMenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourSettingsMenu.png -------------------------------------------------------------------------------- /images/help/AniCourSetupFinished.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourSetupFinished.png -------------------------------------------------------------------------------- /images/help/AniCourSync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourSync.png -------------------------------------------------------------------------------- /images/help/AniCourTokenButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourTokenButton.png -------------------------------------------------------------------------------- /images/help/AniCourTokenLoginPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourTokenLoginPage.png -------------------------------------------------------------------------------- /images/help/AniCourTokenPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourTokenPage.png -------------------------------------------------------------------------------- /images/help/AniCourUsernameAndTokenMessage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourUsernameAndTokenMessage.png -------------------------------------------------------------------------------- /images/help/AniCourUsernameInput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniCourUsernameInput.png -------------------------------------------------------------------------------- /images/help/AniListProfilePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniListProfilePage.png -------------------------------------------------------------------------------- /images/help/AniListProfilePageTooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniListProfilePageTooltip.png -------------------------------------------------------------------------------- /images/help/AniListTokenTooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/help/AniListTokenTooltip.png -------------------------------------------------------------------------------- /images/readme/Advanced/Advanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Advanced/Advanced.png -------------------------------------------------------------------------------- /images/readme/Advanced/AdvancedCropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Advanced/AdvancedCropped.png -------------------------------------------------------------------------------- /images/readme/Advanced/AniCourAdvancedInfo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Advanced/AniCourAdvancedInfo2.png -------------------------------------------------------------------------------- /images/readme/Advanced/AniCourTrailer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Advanced/AniCourTrailer.png -------------------------------------------------------------------------------- /images/readme/AniCourAdvancedInfo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourAdvancedInfo1.png -------------------------------------------------------------------------------- /images/readme/AniCourAdvancedInfo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourAdvancedInfo2.png -------------------------------------------------------------------------------- /images/readme/AniCourAdvancedSideBySide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourAdvancedSideBySide.png -------------------------------------------------------------------------------- /images/readme/AniCourAdvancedThemes2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourAdvancedThemes2.png -------------------------------------------------------------------------------- /images/readme/AniCourAdvancedThemes3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourAdvancedThemes3.png -------------------------------------------------------------------------------- /images/readme/AniCourCompact2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourCompact2.jpg -------------------------------------------------------------------------------- /images/readme/AniCourCompactAndList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourCompactAndList.png -------------------------------------------------------------------------------- /images/readme/AniCourCompactFiltered.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourCompactFiltered.jpg -------------------------------------------------------------------------------- /images/readme/AniCourContextMenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourContextMenu.png -------------------------------------------------------------------------------- /images/readme/AniCourGridView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourGridView.png -------------------------------------------------------------------------------- /images/readme/AniCourGridView2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourGridView2.png -------------------------------------------------------------------------------- /images/readme/AniCourGridView3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourGridView3.png -------------------------------------------------------------------------------- /images/readme/AniCourListView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourListView.png -------------------------------------------------------------------------------- /images/readme/AniCourListViewFiltered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourListViewFiltered.png -------------------------------------------------------------------------------- /images/readme/AniCourNewListView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourNewListView.png -------------------------------------------------------------------------------- /images/readme/AniCourNews.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourNews.png -------------------------------------------------------------------------------- /images/readme/AniCourNews2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourNews2.png -------------------------------------------------------------------------------- /images/readme/AniCourNews3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourNews3.png -------------------------------------------------------------------------------- /images/readme/AniCourNewsAdvanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourNewsAdvanced.png -------------------------------------------------------------------------------- /images/readme/AniCourNewsSideBySide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourNewsSideBySide.png -------------------------------------------------------------------------------- /images/readme/AniCourSearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourSearch.png -------------------------------------------------------------------------------- /images/readme/AniCourSeasons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourSeasons.png -------------------------------------------------------------------------------- /images/readme/AniCourTrailer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/AniCourTrailer.png -------------------------------------------------------------------------------- /images/readme/News/AniCourNews.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/News/AniCourNews.png -------------------------------------------------------------------------------- /images/readme/News/AniCourNewsAdvanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/News/AniCourNewsAdvanced.png -------------------------------------------------------------------------------- /images/readme/News/News.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/News/News.png -------------------------------------------------------------------------------- /images/readme/News/NewsCropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/News/NewsCropped.png -------------------------------------------------------------------------------- /images/readme/Search/AniCourSearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Search/AniCourSearch.png -------------------------------------------------------------------------------- /images/readme/Search/AniCourSearch3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Search/AniCourSearch3.png -------------------------------------------------------------------------------- /images/readme/Search/AniCourSearchFull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Search/AniCourSearchFull.png -------------------------------------------------------------------------------- /images/readme/Search/Search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Search/Search.png -------------------------------------------------------------------------------- /images/readme/Search/SearchCropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/Search/SearchCropped.png -------------------------------------------------------------------------------- /images/readme/SeasonViews/AniCourCompactSeason.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/SeasonViews/AniCourCompactSeason.jpg -------------------------------------------------------------------------------- /images/readme/SeasonViews/AniCourGridViewSeason.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/SeasonViews/AniCourGridViewSeason.png -------------------------------------------------------------------------------- /images/readme/SeasonViews/AniCourGridViewSeason2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/SeasonViews/AniCourGridViewSeason2.png -------------------------------------------------------------------------------- /images/readme/SeasonViews/AniCourListViewSeason.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/SeasonViews/AniCourListViewSeason.png -------------------------------------------------------------------------------- /images/readme/SeasonViews/AniCourSeasonsViews.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/SeasonViews/AniCourSeasonsViews.png -------------------------------------------------------------------------------- /images/readme/SeasonViews/AniCourSeasonsViewsCropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/readme/SeasonViews/AniCourSeasonsViewsCropped.png -------------------------------------------------------------------------------- /images/transfer/ExportMyAnimeList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/transfer/ExportMyAnimeList.png -------------------------------------------------------------------------------- /images/transfer/ImportAniList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/images/transfer/ImportAniList.png -------------------------------------------------------------------------------- /release/app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "anicour", 3 | "version": "1.7.2", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "anicour", 9 | "version": "1.7.2", 10 | "hasInstallScript": true, 11 | "license": "GPL-3.0" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /release/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "anicour", 3 | "version": "1.7.2", 4 | "description": "Anime, Manga, and Light Novel Tracker Desktop Application for Windows. A fast and interactive way for AniList users to track and manage their anime/manga lists. ", 5 | "license": "GPL-3.0", 6 | "author": { 7 | "name": "ReStartQ", 8 | "email": "kevin.hoang322@gmail.com" 9 | }, 10 | "main": "./dist/main/main.js", 11 | "scripts": { 12 | "rebuild": "node -r ts-node/register ../../.erb/scripts/electron-rebuild.js", 13 | "postinstall": "npm run rebuild && npm run link-modules", 14 | "link-modules": "node -r ts-node/register ../../.erb/scripts/link-modules.ts" 15 | }, 16 | "dependencies": {} 17 | } 18 | -------------------------------------------------------------------------------- /release/note.MD: -------------------------------------------------------------------------------- 1 | must put - in place of spaces for files (auto update) 2 | also make a compressed zip file for the exe setup file -------------------------------------------------------------------------------- /src/__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | import { render } from '@testing-library/react'; 3 | import App from '../renderer/App'; 4 | 5 | describe('App', () => { 6 | it('should render', () => { 7 | expect(render()).toBeTruthy(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /src/main/functions/mainFunctions.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/src/main/functions/mainFunctions.ts -------------------------------------------------------------------------------- /src/main/preload.ts: -------------------------------------------------------------------------------- 1 | import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron'; 2 | 3 | export type Channels = 4 | | 'ipc-example' 5 | | 'settings' 6 | | 'toggleTheme' 7 | | 'advancedMedia' 8 | | 'advancedMediaListEntry' 9 | | 'newsList' 10 | | 'newsAdvanced' 11 | | 'changeNews' 12 | | 'resetLogin' 13 | | 'updateMainFromSettings' 14 | | 'updateMainFromAdvanced' 15 | | 'updateAdvancedFromMain' 16 | | 'openExternalLink' 17 | | 'adultFlag' 18 | | 'appVersion'; 19 | 20 | const electronHandler = { 21 | ipcRenderer: { 22 | sendMessage(channel: Channels, ...args: unknown[]) { 23 | ipcRenderer.send(channel, ...args); 24 | }, 25 | on(channel: Channels, func: (...args: unknown[]) => void) { 26 | const subscription = (_event: IpcRendererEvent, ...args: unknown[]) => 27 | func(...args); 28 | ipcRenderer.on(channel, subscription); 29 | 30 | return () => { 31 | ipcRenderer.removeListener(channel, subscription); 32 | }; 33 | }, 34 | once(channel: Channels, func: (...args: unknown[]) => void) { 35 | ipcRenderer.once(channel, (_event, ...args) => func(...args)); 36 | }, 37 | }, 38 | store: { 39 | // this store section was added based on instructions from electron react boilerplate documentation on electron store 40 | get(key: any) { 41 | return ipcRenderer.sendSync('electron-store-get', key); 42 | }, 43 | set(property: any, val: any) { 44 | ipcRenderer.send('electron-store-set', property, val); 45 | }, 46 | has(key: any) { 47 | return ipcRenderer.sendSync('electron-store-has', key); 48 | }, 49 | clear() { 50 | ipcRenderer.send('electron-store-clear', true); 51 | }, 52 | // Other method you want to add like has(), reset(), etc. 53 | }, 54 | }; 55 | 56 | contextBridge.exposeInMainWorld('electron', electronHandler); 57 | 58 | export type ElectronHandler = typeof electronHandler; 59 | -------------------------------------------------------------------------------- /src/renderer/IPC_notes.md: -------------------------------------------------------------------------------- 1 | Here are the methods that the renderer uses to communicate with main: 2 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/CustomTooltip1.tsx: -------------------------------------------------------------------------------- 1 | import { styled } from '@mui/material'; 2 | import Tooltip, { TooltipProps, tooltipClasses } from '@mui/material/Tooltip'; 3 | 4 | const HtmlTooltip = styled(({ className, ...props }: TooltipProps) => ( 5 | // eslint-disable-next-line react/jsx-props-no-spreading 6 | 7 | ))(({ theme }) => ({ 8 | [`& .${tooltipClasses.tooltip}`]: { 9 | backgroundColor: '#0b0d0e', 10 | color: '#86b9db', // #86b9db 11 | fontSize: theme.typography.pxToRem(12), 12 | border: '1px solid #4383ce', // #4383ce 13 | }, 14 | })); 15 | 16 | export default HtmlTooltip; 17 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/CustomTooltipFixedWidth.tsx: -------------------------------------------------------------------------------- 1 | import { styled } from '@mui/material'; 2 | import Tooltip, { TooltipProps, tooltipClasses } from '@mui/material/Tooltip'; 3 | 4 | const CustomToolTipFixedWidth = styled( 5 | ({ className, ...props }: TooltipProps) => ( 6 | // eslint-disable-next-line react/jsx-props-no-spreading 7 | 8 | ), 9 | )(({ theme }) => ({ 10 | [`& .${tooltipClasses.tooltip}`]: { 11 | backgroundColor: '#0b0d0e', 12 | color: '#86b9db', // #86b9db 13 | fontSize: theme.typography.pxToRem(12), 14 | border: '1px solid #4383ce', // #4383ce 15 | maxWidth: 600, 16 | }, 17 | })); 18 | 19 | export default CustomToolTipFixedWidth; 20 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/ErrorAPI.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Typography } from '@mui/material'; 2 | import React from 'react'; 3 | 4 | const ErrorAPI = () => { 5 | return ( 6 | 15 | 16 | Failed to fetch data from the API service 17 | 18 | 19 | ); 20 | }; 21 | 22 | export default ErrorAPI; 23 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/ErrorCredentials.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Typography } from '@mui/material'; 2 | import React from 'react'; 3 | 4 | const ErrorCredentials = () => { 5 | return ( 6 | 15 | 16 | 17 | Please set the username and token in the settings menu. 18 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default ErrorCredentials; 25 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/ErrorNewsFetch.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Typography } from '@mui/material'; 2 | import React from 'react'; 3 | import { useNewsServiceType } from 'renderer/context/NewsServiceTypeContext'; 4 | 5 | const ErrorNewsFetch = () => { 6 | const newsServiceType: any = useNewsServiceType(); 7 | return ( 8 | 17 | 18 | 19 | Failed to fetch news from{' '} 20 | { 21 | newsServiceType.news ? 'MyAnimeList' : 'AnimeNewsNetwork' // true = myanimelist, false = animenewsnetwork 22 | } 23 | 24 | 25 | 26 | ); 27 | }; 28 | 29 | export default ErrorNewsFetch; 30 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/LoadingMessage.tsx: -------------------------------------------------------------------------------- 1 | import { CircularProgress } from '@mui/joy'; 2 | import { Box, Typography } from '@mui/material'; 3 | import React from 'react'; 4 | 5 | const Loading = () => { 6 | return ( 7 | 16 | 17 | 18 | Loading 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default Loading; 25 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/LoadingNews.tsx: -------------------------------------------------------------------------------- 1 | import { CircularProgress } from '@mui/joy'; 2 | import { Box, Typography } from '@mui/material'; 3 | import React from 'react'; 4 | 5 | const LoadingNews = () => { 6 | return ( 7 | 16 | 17 | 18 | Loading 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default LoadingNews; 25 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/MediaProgress.tsx: -------------------------------------------------------------------------------- 1 | import { LinearProgress } from '@mui/material'; 2 | import React from 'react'; 3 | 4 | const MediaProgress = ({ 5 | progress, 6 | buffer, 7 | progressRaw, 8 | episodes, 9 | chapters, 10 | volumes, 11 | mediaType, 12 | type, 13 | }: any) => { 14 | // MIN = Minimum expected value 15 | // MAX = Maximum expected value 16 | // Function to normalise the values (MIN / MAX could be integrated) 17 | // const normalise = (value) => ((value - MIN) * 100) / (MAX - MIN); 18 | function getLength(number: any) { 19 | if (number !== null) { 20 | return number.toString().length; 21 | } 22 | return 1; 23 | } 24 | 25 | const getWidth = ( 26 | rawValue: any, 27 | ep: any, 28 | ch: any, 29 | vol: any, 30 | typeMedia: any, 31 | progressType: any, 32 | ) => { 33 | // eslint-disable-next-line prefer-const 34 | let counter = 0; 35 | if (progressType === 0) { 36 | if (typeMedia === 'ANIME') { 37 | counter += getLength(rawValue) + getLength(ep); 38 | } else { 39 | counter += getLength(rawValue) + getLength(ch); 40 | } 41 | } 42 | if (progressType === 1) { 43 | counter += getLength(rawValue) + getLength(vol); 44 | } 45 | switch (counter) { 46 | case 2: 47 | // g 48 | return '66%'; 49 | case 3: 50 | // g 51 | return '71%'; 52 | case 4: 53 | // g 54 | return '78%'; 55 | case 5: 56 | // g 57 | return '85%'; 58 | case 6: 59 | // g 60 | return '88%'; 61 | case 7: 62 | // g 63 | return '92%'; 64 | default: // 8 g 65 | return '95%'; 66 | } 67 | }; 68 | 69 | return ( 70 | 85 | ); 86 | }; 87 | 88 | export default MediaProgress; 89 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/NextAiringEpisodeIndicator.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip } from '@mui/joy'; 2 | import InfoIcon from '@mui/icons-material/Info'; 3 | import { Box, IconButton, Typography } from '@mui/material'; 4 | import MediaProgress from './MediaProgress'; 5 | 6 | const NextAiringEpisodeIndicator = ({ props, progress }: any) => { 7 | const normalise = (value: number) => 8 | ((value - 0) * 100) / 9 | (props.episodes !== null ? props.episodes - 0 : 26 - 0); 10 | 11 | return ( 12 | 13 | 14 | {props.type === 'ANIME' ? 'Episodes' : 'Chapters'} 15 | 16 | 27 | 39 | 44 | 45 | 46 | 47 | ); 48 | }; 49 | 50 | export default NextAiringEpisodeIndicator; 51 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/ProgressBar.tsx: -------------------------------------------------------------------------------- 1 | import AddIcon from '@mui/icons-material/Add'; 2 | import RemoveIcon from '@mui/icons-material/Remove'; 3 | import { Box, IconButton } from '@mui/material'; 4 | 5 | export default function ProgressBar({ props }: any) { 6 | return ( 7 | 8 | Episodes: 9 | 10 | 11 | 12 | 120000/120000 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/ResetMenuApp.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Button, 3 | Dialog, 4 | DialogActions, 5 | DialogContent, 6 | DialogContentText, 7 | DialogTitle, 8 | } from '@mui/material'; 9 | import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew'; 10 | import React from 'react'; 11 | import { useAtom } from 'jotai'; 12 | import { appResetDialogOpenAtom } from 'renderer/store'; 13 | 14 | const ResetMenuApp = () => { 15 | const [open, setOpen] = useAtom(appResetDialogOpenAtom); 16 | 17 | const handleClickOpen = () => { 18 | setOpen(true); 19 | }; 20 | 21 | const handleClose = (value: boolean) => { 22 | setOpen(false); 23 | if (value) { 24 | window.electron.store.clear(); 25 | } 26 | // update in main 27 | }; 28 | return ( 29 |
30 | 36 | 37 | Reset app data to default? 38 | 39 | 40 | 41 | This will reset all settings to default. 42 |
43 | Your account settings data will be reset and you will have to 44 | reconnect your account to the app. 45 |
46 |
47 | 48 | 56 | 59 | 60 |
61 |
62 | ); 63 | }; 64 | 65 | export default ResetMenuApp; 66 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableAverageScore.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | 4 | const TableAverageScore = ({ row }: any) => { 5 | return ( 6 | 7 | {row.averageScore !== null ? `${row.averageScore}%` : '?'} 8 | 9 | ); 10 | }; 11 | 12 | export default TableAverageScore; 13 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableChapters.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | 4 | const TableChapters = ({ row }: any) => { 5 | return ( 6 | 7 | {row.chapters !== null ? row.chapters : '?'} 8 | 9 | ); 10 | }; 11 | 12 | export default TableChapters; 13 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableEpisodes.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | 4 | const TableEpisodes = ({ row }: any) => { 5 | return ( 6 | 7 | {row.episodes !== null ? row.episodes : '?'} 8 | 9 | ); 10 | }; 11 | 12 | export default TableEpisodes; 13 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableReleased.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import { formatReleaseDateNumbers } from 'renderer/functions/edit/formatInfo'; 3 | 4 | const TableReleased = ({ row }: any) => { 5 | return ( 6 | 7 | {formatReleaseDateNumbers(row.startDay, row.startMonth, row.startYear)} 8 | 9 | ); 10 | }; 11 | 12 | export default TableReleased; 13 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableScore.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | 4 | const TableScore = ({ row }: any) => { 5 | return ( 6 | 7 | {row.mediaListEntry.score === 0 ? '' : row.mediaListEntry.score} 8 | 9 | ); 10 | }; 11 | 12 | export default TableScore; 13 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableSeason.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | import { 4 | formatSeason, 5 | formatStartYear, 6 | } from 'renderer/functions/edit/formatInfo'; 7 | 8 | const TableSeason = ({ row }: any) => { 9 | return ( 10 | 11 | {row.season !== null && row.seasonYear !== null 12 | ? formatSeason(row.season, row.seasonYear) 13 | : formatStartYear(row.startYear)} 14 | 15 | ); 16 | }; 17 | 18 | export default TableSeason; 19 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableStatus.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { formatStatus } from 'renderer/functions/edit/formatInfo'; 3 | import getStatusColor from 'renderer/functions/StatusFunction'; 4 | import CircleIcon from '@mui/icons-material/Circle'; 5 | import HtmlTooltip from '../CustomTooltip1'; 6 | 7 | const TableStatus = ({ row }: any) => { 8 | return ( 9 | 10 | 19 | 20 | ); 21 | }; 22 | 23 | export default TableStatus; 24 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableTitleMain.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | import MessageIcon from '@mui/icons-material/Message'; 4 | import RepeatIcon from '@mui/icons-material/Repeat'; 5 | import { useTitle } from 'renderer/context/TitleContext'; 6 | import { getTitle } from 'renderer/functions/view/TitlePreferenceFunctions'; 7 | import { useCategory } from 'renderer/context/CategoryContext'; 8 | import { useSidebarButton } from 'renderer/context/SidebarContext'; 9 | import HtmlTooltip from '../CustomTooltip1'; 10 | 11 | const TableTitleMain = ({ row }: any) => { 12 | const myTitlePreference: any = useTitle(); 13 | const myCategory: any = useCategory(); 14 | const mySidebar: any = useSidebarButton(); 15 | 16 | return ( 17 | 18 | {row.mediaListEntry.notes !== null ? ( 19 | 20 | 21 | 22 | ) : null} 23 | {(row.mediaListEntry.repeat > 0 || 24 | row.mediaListEntry.completedAt.year !== null) && 25 | myCategory.category !== 1 && 26 | myCategory.category !== 5 ? ( 27 | 30 | 31 | 32 | ) : null} 33 | {getTitle(myTitlePreference.title, row)} 34 | 35 | ); 36 | }; 37 | 38 | export default TableTitleMain; 39 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableTitleOther.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | import PlaylistAddCheckCircleIcon from '@mui/icons-material/PlaylistAddCheckCircle'; 4 | import { useTitle } from 'renderer/context/TitleContext'; 5 | import { getTitle } from 'renderer/functions/view/TitlePreferenceFunctions'; 6 | import { useSearchTerm } from 'renderer/context/SearchTermContext'; 7 | import { useAniListToken } from 'renderer/context/services/AniListTokenContext'; 8 | import { useAdult } from 'renderer/context/AdultContext'; 9 | import { useSearchQuery } from 'renderer/functions/SearchFunctions'; 10 | import { useSeasonsQuery } from 'renderer/functions/SeasonsFunctions'; 11 | import { useSeasonInput } from 'renderer/context/SeasonInputContext'; 12 | import { useAniListUsername } from 'renderer/context/services/AniListUsernameContext'; 13 | import HtmlTooltip from '../CustomTooltip1'; 14 | 15 | const TableTitleOther = ({ row }: any) => { 16 | const myTitlePreference: any = useTitle(); 17 | const searchTerm: any = useSearchTerm(); 18 | const myToken: any = useAniListToken(); 19 | const adult: any = useAdult(); 20 | const seasonInput: any = useSeasonInput(); 21 | const myUserName: any = useAniListUsername(); 22 | 23 | // this fixes the setQuery not reupdating 24 | const searchObject = useSearchQuery( 25 | searchTerm.SearchTerm, 26 | myToken.AniListToken, 27 | adult.adult, 28 | ); 29 | // this fixes the setQuery not reupdating 30 | const seasonObject = useSeasonsQuery( 31 | seasonInput.seasonInput, 32 | myToken.AniListToken, 33 | myUserName.AniListUsername, 34 | adult.adult, 35 | ); 36 | 37 | return ( 38 | 39 | {row.mediaListEntry !== null ? ( 40 | 41 | 42 | 43 | ) : null} 44 | {getTitle(myTitlePreference.title, row)} 45 | 46 | ); 47 | }; 48 | 49 | export default TableTitleOther; 50 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableType.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | import { formatType } from 'renderer/functions/edit/formatInfo'; 4 | 5 | const TableType = ({ row }: any) => { 6 | return ( 7 | 8 | {row.format !== null ? formatType(row.format) : '?'} 9 | 10 | ); 11 | }; 12 | 13 | export default TableType; 14 | -------------------------------------------------------------------------------- /src/renderer/components/app/etc/table/TableVolumes.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import React from 'react'; 3 | 4 | const TableVolumes = ({ row }: any) => { 5 | return ( 6 | 7 | {row.volumes !== null ? row.volumes : '?'} 8 | 9 | ); 10 | }; 11 | 12 | export default TableVolumes; 13 | -------------------------------------------------------------------------------- /src/renderer/components/app/history/HistoryButton.tsx: -------------------------------------------------------------------------------- 1 | import { IconButton } from '@mui/joy'; 2 | import HistoryIcon from '@mui/icons-material/History'; 3 | import React from 'react'; 4 | import { useSidebarButton } from 'renderer/context/SidebarContext'; 5 | 6 | const HistoryButton = () => { 7 | const mySideBar: any = useSidebarButton(); 8 | 9 | const onClick = () => { 10 | mySideBar.setSidebar(6); 11 | }; 12 | 13 | return ( 14 | 15 | 16 | 17 | ); 18 | }; 19 | 20 | export default HistoryButton; 21 | -------------------------------------------------------------------------------- /src/renderer/components/app/main/MainTabLi.tsx: -------------------------------------------------------------------------------- 1 | import { useCategory } from 'renderer/context/CategoryContext'; 2 | import { useFilter } from 'renderer/context/FilterContext'; 3 | import { useSidebarButton } from 'renderer/context/SidebarContext'; 4 | import { useAniListToken } from 'renderer/context/services/AniListTokenContext'; 5 | import { useAniListUsername } from 'renderer/context/services/AniListUsernameContext'; 6 | import { useMainMediaList } from 'renderer/functions/MainMediaListFunctions'; 7 | import { useSort } from 'renderer/context/SortContext'; 8 | import { useTitle } from 'renderer/context/TitleContext'; 9 | import ErrorAPI from '../etc/ErrorAPI'; 10 | import ErrorCredentials from '../etc/ErrorCredentials'; 11 | import LoadingMessage from '../etc/LoadingMessage'; 12 | import MainTabList from './MainTabList'; 13 | 14 | const MainTabLi = ({ props }: any) => { 15 | const myTitle: any = useTitle(); 16 | const myFilter: any = useFilter(); 17 | const myToken: any = useAniListToken(); 18 | const myUsername: any = useAniListUsername(); 19 | const mySidebar: any = useSidebarButton(); 20 | const myCategory: any = useCategory(); 21 | const mySort: any = useSort(); 22 | 23 | const { isLoading, isError, error, data, refetch }: any = useMainMediaList( 24 | myUsername.AniListUsername, 25 | myToken.AniListToken, 26 | ); 27 | 28 | if (isLoading) { 29 | return ; 30 | } 31 | 32 | if (isError && error.response !== undefined) { 33 | if (error.response.status === 400) return ; 34 | } 35 | 36 | if (isError && error.response !== undefined) { 37 | if (error.response.status !== 400) return ; 38 | } 39 | 40 | if (isError && error.response === undefined) { 41 | return ; 42 | } 43 | 44 | return ; 45 | }; 46 | 47 | export default MainTabLi; 48 | -------------------------------------------------------------------------------- /src/renderer/components/app/main/MediaDataGrid.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/jsx-props-no-spreading */ 2 | import * as React from 'react'; 3 | import { DataGrid, GridColDef, GridRowId } from '@mui/x-data-grid'; 4 | 5 | export interface DataRowModel { 6 | id: GridRowId; 7 | [price: string]: number | string; 8 | } 9 | 10 | export interface GridData { 11 | columns: GridColDef[]; 12 | rows: DataRowModel[]; 13 | } 14 | 15 | function useData(rowLength: number, columnLength: number) { 16 | const [data, setData] = React.useState({ columns: [], rows: [] }); 17 | 18 | React.useEffect(() => { 19 | const rows: DataRowModel[] = []; 20 | 21 | for (let i = 0; i < rowLength; i += 1) { 22 | const row: DataRowModel = { 23 | id: i, 24 | }; 25 | 26 | for (let j = 1; j <= columnLength; j += 1) { 27 | row[`price${j}M`] = `${i.toString()}, ${j} `; 28 | } 29 | 30 | rows.push(row); 31 | } 32 | 33 | const columns: GridColDef[] = []; 34 | 35 | for (let j = 1; j <= columnLength; j += 1) { 36 | columns.push({ field: `price${j}M`, headerName: `${j}M` }); 37 | } 38 | 39 | setData({ 40 | rows, 41 | columns, 42 | }); 43 | }, [rowLength, columnLength]); 44 | 45 | return data; 46 | } 47 | 48 | export default function MediaDataGrid({ props }: any) { 49 | const data = useData(1000, 5); 50 | 51 | return ( 52 |
53 | 54 |
55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /src/renderer/components/app/main/cards/MainSkeletonCards.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReStartQ/anicour/40ee6feff289c88c6466640ffab2ceb62230909e/src/renderer/components/app/main/cards/MainSkeletonCards.tsx -------------------------------------------------------------------------------- /src/renderer/components/app/main/tables/makeData.ts: -------------------------------------------------------------------------------- 1 | import { faker } from '@faker-js/faker'; 2 | 3 | export type Person = { 4 | id: number; 5 | firstName: string; 6 | lastName: string; 7 | age: number; 8 | visits: number; 9 | progress: number; 10 | status: 'relationship' | 'complicated' | 'single'; 11 | createdAt: Date; 12 | }; 13 | 14 | const range = (len: number) => { 15 | const arr: number[] = []; 16 | // eslint-disable-next-line no-plusplus 17 | for (let i = 0; i < len; i++) { 18 | arr.push(i); 19 | } 20 | return arr; 21 | }; 22 | 23 | const newPerson = (index: number): Person => { 24 | return { 25 | id: index + 1, 26 | firstName: faker.person.firstName(), 27 | lastName: faker.person.lastName(), 28 | age: faker.number.int(40), 29 | visits: faker.number.int(1000), 30 | progress: faker.number.int(100), 31 | createdAt: faker.date.anytime(), 32 | status: faker.helpers.shuffle([ 33 | 'relationship', 34 | 'complicated', 35 | 'single', 36 | ])[0]!, 37 | }; 38 | }; 39 | 40 | export function makeData(...lens: number[]) { 41 | const makeDataLevel = (depth = 0): Person[] => { 42 | const len = lens[depth]!; 43 | return range(len).map((d): Person => { 44 | return { 45 | ...newPerson(d), 46 | }; 47 | }); 48 | }; 49 | 50 | return makeDataLevel(); 51 | } 52 | -------------------------------------------------------------------------------- /src/renderer/components/app/news/NewsAdvanced.tsx: -------------------------------------------------------------------------------- 1 | import { Card, CardContent, Divider, Link, Typography } from '@mui/material'; 2 | import parse from 'html-react-parser'; 3 | import { memo, useEffect } from 'react'; 4 | import { useNewsInfo } from 'renderer/context/NewsInfoContext'; 5 | import { useNewsServiceType } from 'renderer/context/NewsServiceTypeContext'; 6 | import 'renderer/styles/NewsAdvanced.scss'; 7 | import LoadingNews from '../etc/LoadingNews'; 8 | 9 | const NewsAdvanced = memo(({ props }: any) => { 10 | const myNewsInfo: any = useNewsInfo(); 11 | const myService: any = useNewsServiceType(); 12 | 13 | useEffect(() => { 14 | const removeEventListener = window.electron.ipcRenderer.on( 15 | 'newsAdvanced', 16 | (arg) => { 17 | // eslint-disable-next-line no-console 18 | if (myNewsInfo.NewsInfo !== arg) { 19 | console.log(arg); 20 | myNewsInfo.setNewsInfo(arg); 21 | } 22 | }, 23 | ); 24 | return () => { 25 | removeEventListener(); 26 | }; 27 | }, [myNewsInfo, myService.news]); 28 | 29 | return myNewsInfo.NewsInfo.title !== '' ? ( 30 | 40 | 41 | 47 | 48 | {parse(myNewsInfo.NewsInfo.title)} 49 | 50 | 51 | 52 | 53 | 54 | 55 | {parse(myNewsInfo.NewsInfo.date)} 56 | 57 | 58 | {parse(myNewsInfo.NewsInfo.main)} 59 | 60 | 61 | 62 | ) : ( 63 | 64 | ); 65 | }); 66 | 67 | export default NewsAdvanced; 68 | 69 | // add target = _blank to a tags and add allowfullscreen to iframe. Also look at special html characters when converting to string. 70 | -------------------------------------------------------------------------------- /src/renderer/components/app/news/NewsBar.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Drawer, 3 | List, 4 | ListItem, 5 | ListItemButton, 6 | ListItemIcon, 7 | } from '@mui/material'; 8 | import { useNewsAdv } from 'renderer/context/NewsAdvContext'; 9 | import ArrowBackIcon from '@mui/icons-material/ArrowBack'; 10 | import { useNewsInfo } from 'renderer/context/NewsInfoContext'; 11 | import { useNavigate } from 'react-router-dom'; 12 | 13 | export default function NewsBack({ props }: any) { 14 | const newsAdv: any = useNewsAdv(); 15 | const myNewsInfo: any = useNewsInfo(); 16 | const navigate = useNavigate(); 17 | 18 | return ( 19 | 24 | 25 | {['Back'].map((text, index) => ( 26 | 27 | { 33 | newsAdv.toggleNews(); 34 | myNewsInfo.setNewsInfo({ 35 | title: '', 36 | titleURL: '', 37 | author: '', 38 | authorUrl: '', 39 | main: '', 40 | date: '', 41 | }); 42 | navigate('/'); 43 | }} 44 | > 45 | 50 | 51 | 52 | 53 | 54 | ))} 55 | 56 | 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /src/renderer/components/app/news/NewsButtons.tsx: -------------------------------------------------------------------------------- 1 | import Box from '@mui/material/Box'; 2 | 3 | export default function NewsButtons({ props }: any) { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/renderer/components/app/news/NewsButtonsAdvanced.tsx: -------------------------------------------------------------------------------- 1 | import Box from '@mui/material/Box'; 2 | 3 | import NewsBack from './NewsBar'; 4 | 5 | export default function NewsButtonsAdvanced({ props }: any) { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /src/renderer/components/app/news/NewsFullscreen.tsx: -------------------------------------------------------------------------------- 1 | import FullscreenIcon from '@mui/icons-material/Fullscreen'; 2 | import { IconButton } from '@mui/material'; 3 | 4 | export default function NewsFullscreen({ props }: any) { 5 | const handleClick = () => { 6 | console.log('fullscreen'); 7 | }; 8 | 9 | return ( 10 | 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/renderer/components/app/news/NewsRefresh.tsx: -------------------------------------------------------------------------------- 1 | import RefreshIcon from '@mui/icons-material/Refresh'; 2 | import { ToggleButton, Typography } from '@mui/material'; 3 | import { useState } from 'react'; 4 | import { useNews } from 'renderer/context/NewsContext'; 5 | import { useNewsServiceType } from 'renderer/context/NewsServiceTypeContext'; 6 | import { useNewsQuery } from 'renderer/functions/NewsFunctions'; 7 | import isOnline from 'is-online'; 8 | import HtmlTooltip from '../etc/CustomTooltip1'; 9 | 10 | export default function NewsRefresh({ props }: any) { 11 | const newsCards: any = useNews(); 12 | const newsServiceType: any = useNewsServiceType(); 13 | 14 | const { data, refetch } = useNewsQuery(newsCards); 15 | const [isDisabled, setIsDisabled] = useState(false); 16 | 17 | async function fetchAPI() { 18 | setIsDisabled(true); 19 | let checkOnline = false; 20 | checkOnline = await isOnline(); 21 | console.log(checkOnline); 22 | if (checkOnline) { 23 | await refetch(); 24 | } 25 | setIsDisabled(false); 26 | } 27 | 28 | const handleClick = () => { 29 | if (newsServiceType.news === true) { 30 | fetchAPI(); 31 | } else { 32 | window.electron.ipcRenderer.sendMessage('newsList', ['ping']); 33 | } 34 | console.log(newsServiceType.news); 35 | }; 36 | 37 | return ( 38 | 41 | 42 | Refresh News 43 | 44 | 45 | } 46 | placement="top" 47 | > 48 | 54 | 55 | 56 | 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /src/renderer/components/app/search/SearchTabLi.tsx: -------------------------------------------------------------------------------- 1 | import { useCategory } from 'renderer/context/CategoryContext'; 2 | import { useFilter } from 'renderer/context/FilterContext'; 3 | import { useSidebarButton } from 'renderer/context/SidebarContext'; 4 | import { useAniListToken } from 'renderer/context/services/AniListTokenContext'; 5 | import { useAniListUsername } from 'renderer/context/services/AniListUsernameContext'; 6 | import { useSort } from 'renderer/context/SortContext'; 7 | import { useTitle } from 'renderer/context/TitleContext'; 8 | import { useSearchQuery } from 'renderer/functions/SearchFunctions'; 9 | import { useSearchTerm } from 'renderer/context/SearchTermContext'; 10 | import { useAdult } from 'renderer/context/AdultContext'; 11 | import LoadingMessage from '../etc/LoadingMessage'; 12 | import ErrorCredentials from '../etc/ErrorCredentials'; 13 | import ErrorAPI from '../etc/ErrorAPI'; 14 | import SearchTabList from './SearchTabList'; 15 | 16 | const SearchTabLi = ({ props }: any) => { 17 | const myTitle: any = useTitle(); 18 | const myFilter: any = useFilter(); 19 | const myToken: any = useAniListToken(); 20 | const myUsername: any = useAniListUsername(); 21 | const searchTerm: any = useSearchTerm(); 22 | const mySidebar: any = useSidebarButton(); 23 | const adult: any = useAdult(); 24 | const myCategory: any = useCategory(); 25 | const mySort: any = useSort(); 26 | 27 | const { isLoading, isError, error, data, refetch, dataUpdatedAt }: any = 28 | useSearchQuery(searchTerm.SearchTerm, myToken.AniListToken, adult.adult); 29 | 30 | if (isLoading) { 31 | return ; 32 | } 33 | 34 | if (isError && error.response !== undefined) { 35 | if (error.response.status === 400) return ; 36 | } 37 | 38 | if (isError && error.response !== undefined) { 39 | if (error.response.status !== 400) return ; 40 | } 41 | 42 | if (isError && error.response === undefined) { 43 | return ; 44 | } 45 | 46 | return ; 47 | }; 48 | 49 | export default SearchTabLi; 50 | -------------------------------------------------------------------------------- /src/renderer/components/app/search/tables/SearchTitleTableBox.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Typography } from '@mui/material'; 2 | import React from 'react'; 3 | import { getTitle } from 'renderer/functions/view/TitlePreferenceFunctions'; 4 | import { useTitle } from 'renderer/context/TitleContext'; 5 | import { useSearchTerm } from 'renderer/context/SearchTermContext'; 6 | import { useAniListToken } from 'renderer/context/services/AniListTokenContext'; 7 | import { useAdult } from 'renderer/context/AdultContext'; 8 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 9 | import { useSearchQuery } from 'renderer/functions/SearchFunctions'; 10 | import { OnListIcon } from '../../etc/SvgIcons'; 11 | 12 | const SearchTitleTableBox = ({ title, row }: any) => { 13 | const titlePreference: any = useTitle(); 14 | const searchTerm: any = useSearchTerm(); 15 | const myToken: any = useAniListToken(); 16 | const adult: any = useAdult(); 17 | const myAdvancedMedia: any = useAdvancedMedia(); 18 | 19 | // this fixes the setQuery not reupdating 20 | const { data, refetch, dataUpdatedAt } = useSearchQuery( 21 | searchTerm.SearchTerm, 22 | myToken.AniListToken, 23 | adult.adult, 24 | ); 25 | 26 | return ( 27 | 28 | {row.mediaListEntry !== null ? : null} 29 | 30 | {getTitle(title, row)} 31 | 32 | 33 | ); 34 | }; 35 | 36 | export default SearchTitleTableBox; 37 | -------------------------------------------------------------------------------- /src/renderer/components/app/seasons/SeasonMenu.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const SeasonMenu = () => { 4 | return
SeasonMenu
; 5 | }; 6 | 7 | export default SeasonMenu; 8 | -------------------------------------------------------------------------------- /src/renderer/components/app/seasons/SeasonTabLi.tsx: -------------------------------------------------------------------------------- 1 | import { useCategory } from 'renderer/context/CategoryContext'; 2 | import { useFilter } from 'renderer/context/FilterContext'; 3 | import { useSidebarButton } from 'renderer/context/SidebarContext'; 4 | import { useAniListToken } from 'renderer/context/services/AniListTokenContext'; 5 | import { useAniListUsername } from 'renderer/context/services/AniListUsernameContext'; 6 | import { useSort } from 'renderer/context/SortContext'; 7 | import { useTitle } from 'renderer/context/TitleContext'; 8 | import { useSearchTerm } from 'renderer/context/SearchTermContext'; 9 | import { useAdult } from 'renderer/context/AdultContext'; 10 | import { useSeasonInput } from 'renderer/context/SeasonInputContext'; 11 | import { useSeasonsQuery } from 'renderer/functions/SeasonsFunctions'; 12 | import LoadingMessage from '../etc/LoadingMessage'; 13 | import ErrorCredentials from '../etc/ErrorCredentials'; 14 | import ErrorAPI from '../etc/ErrorAPI'; 15 | import SeasonTabList from './SeasonTabList'; 16 | 17 | const SeasonTabLi = ({ props }: any) => { 18 | const myTitle: any = useTitle(); 19 | const myFilter: any = useFilter(); 20 | const myToken: any = useAniListToken(); 21 | const myUsername: any = useAniListUsername(); 22 | const searchTerm: any = useSearchTerm(); 23 | const mySidebar: any = useSidebarButton(); 24 | const adult: any = useAdult(); 25 | const myCategory: any = useCategory(); 26 | const mySort: any = useSort(); 27 | const seasonInput: any = useSeasonInput(); 28 | const myUserName: any = useAniListUsername(); 29 | 30 | const { isLoading, isError, error, data, refetch, dataUpdatedAt }: any = 31 | useSeasonsQuery( 32 | seasonInput.seasonInput, 33 | myToken.AniListToken, 34 | myUserName.AniListUsername, 35 | adult.adult, 36 | ); 37 | 38 | if (isLoading) { 39 | return ; 40 | } 41 | 42 | if (isError && error.response !== undefined) { 43 | if (error.response.status === 400) return ; 44 | } 45 | 46 | if (isError && error.response !== undefined) { 47 | if (error.response.status !== 400) return ; 48 | } 49 | 50 | if (isError && error.response === undefined) { 51 | return ; 52 | } 53 | 54 | return ; 55 | }; 56 | 57 | export default SeasonTabLi; 58 | -------------------------------------------------------------------------------- /src/renderer/components/app/seasons/tables/SeasonTitleTableBox.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Typography } from '@mui/material'; 2 | import React from 'react'; 3 | import { getTitle } from 'renderer/functions/view/TitlePreferenceFunctions'; 4 | import { useTitle } from 'renderer/context/TitleContext'; 5 | import { useSearchTerm } from 'renderer/context/SearchTermContext'; 6 | import { useAniListToken } from 'renderer/context/services/AniListTokenContext'; 7 | import { useAdult } from 'renderer/context/AdultContext'; 8 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 9 | import { useSeasonsQuery } from 'renderer/functions/SeasonsFunctions'; 10 | import { useSeasonInput } from 'renderer/context/SeasonInputContext'; 11 | import { useAniListUsername } from 'renderer/context/services/AniListUsernameContext'; 12 | import { OnListIcon } from '../../etc/SvgIcons'; 13 | 14 | const SeasonTitleTableBox = ({ title, row }: any) => { 15 | const titlePreference: any = useTitle(); 16 | const searchTerm: any = useSearchTerm(); 17 | const myToken: any = useAniListToken(); 18 | const adult: any = useAdult(); 19 | const myAdvancedMedia: any = useAdvancedMedia(); 20 | const seasonInput: any = useSeasonInput(); 21 | const myUserName: any = useAniListUsername(); 22 | 23 | // this fixes the setQuery not reupdating 24 | const { data, refetch, dataUpdatedAt } = useSeasonsQuery( 25 | seasonInput.seasonInput, 26 | myToken.AniListToken, 27 | myUserName.AniListUsername, 28 | adult.adult, 29 | ); 30 | 31 | return ( 32 | 33 | {row.mediaListEntry !== null ? : null} 34 | 35 | {getTitle(title, row)} 36 | 37 | 38 | ); 39 | }; 40 | 41 | export default SeasonTitleTableBox; 42 | -------------------------------------------------------------------------------- /src/renderer/components/app/sidebar/FeatureButtonGroupNews.tsx: -------------------------------------------------------------------------------- 1 | import SettingsIcon from '@mui/icons-material/Settings'; 2 | import { ToggleButton, ToggleButtonGroup, Typography } from '@mui/material'; 3 | import NewsRefresh from '../news/NewsRefresh'; 4 | import HtmlTooltip from '../etc/CustomTooltip1'; 5 | 6 | export default function FeatureButtonGroupNews() { 7 | /* 8 | useEffect(() => { 9 | if (myUsername.AniListUsername !== '' && myToken.AniListToken !== '') { 10 | fetchAPI(); 11 | } 12 | // eslint-disable-next-line react-hooks/exhaustive-deps 13 | }, [myUsername.AniListUsername, myToken.AniListToken]); 14 | */ 15 | return ( 16 | 21 | 22 | 25 | 26 | Settings 27 | 28 | 29 | } 30 | placement="top" 31 | > 32 | { 36 | window.electron.ipcRenderer.sendMessage('settings', ['ping']); 37 | }} 38 | > 39 | 40 | 41 | 42 | 43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/renderer/components/app/test/MediaProgress.tsx: -------------------------------------------------------------------------------- 1 | import { IconButtonProps } from '@mui/material/IconButton'; 2 | 3 | interface MediaProps { 4 | titleRomaji: string; 5 | image: string; 6 | key: number; 7 | } 8 | 9 | interface ExpandMoreProps extends IconButtonProps { 10 | expand: boolean; 11 | } 12 | 13 | export default function MediaCardCompact({ props }: any) { 14 | return <>dog; 15 | } 16 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/AdvancedMain.tsx: -------------------------------------------------------------------------------- 1 | import { useColorScheme as useJoyColorScheme } from '@mui/joy/styles'; 2 | import { Paper } from '@mui/material'; 3 | import { useColorScheme as useMaterialColorScheme } from '@mui/material/styles'; 4 | import { useEffect } from 'react'; 5 | import { useTheme } from 'renderer/context/ThemeContext'; 6 | import AdvancedDescription from './description/AdvancedDescription'; 7 | import EntryInputOnList from './entryInput/onList/EntryInputOnList'; 8 | import AdvancedExtra from './extra/AdvancedExtra'; 9 | import AdvancedImage from './image/AdvancedImage'; 10 | import AdvancedInformation from './information/AdvancedInformation'; 11 | import AdvancedTitle from './title/AdvancedTitle'; 12 | 13 | export default function AdvancedMain({ props }: any) { 14 | const myTheme: any = useTheme(); 15 | const { setMode: setJoyMode } = useJoyColorScheme(); 16 | const { mode, setMode: setMaterialMode } = useMaterialColorScheme(); 17 | 18 | useEffect(() => { 19 | if (myTheme.theme === true) { 20 | setJoyMode('dark'); 21 | setMaterialMode('dark'); 22 | } else { 23 | setJoyMode('light'); 24 | setMaterialMode('light'); 25 | } 26 | }, [myTheme, setJoyMode, setMaterialMode]); 27 | 28 | return ( 29 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ); 50 | } 51 | 52 | // title is a 2 liner 53 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/AdvancedMainNOL.tsx: -------------------------------------------------------------------------------- 1 | import { useColorScheme as useJoyColorScheme } from '@mui/joy/styles'; 2 | import { Paper } from '@mui/material'; 3 | import Box from '@mui/material/Box'; 4 | import { useColorScheme as useMaterialColorScheme } from '@mui/material/styles'; 5 | import { useEffect } from 'react'; 6 | import { useTheme } from 'renderer/context/ThemeContext'; 7 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 8 | import AdvancedDescription from './description/AdvancedDescription'; 9 | import EntryInputNotOnList from './entryInput/notOnList/EntryInputNotOnList'; 10 | import AdvancedExtra from './extra/AdvancedExtra'; 11 | import AdvancedImage from './image/AdvancedImage'; 12 | import AdvancedInformation from './information/AdvancedInformation'; 13 | import AdvancedTitle from './title/AdvancedTitle'; 14 | 15 | export default function AdvancedMainNOL({ props }: any) { 16 | const myAdvancedMedia: any = useAdvancedMedia(); 17 | const myTheme: any = useTheme(); 18 | const { setMode: setJoyMode } = useJoyColorScheme(); 19 | const { mode, setMode: setMaterialMode } = useMaterialColorScheme(); 20 | 21 | useEffect(() => { 22 | if (myTheme.theme === true) { 23 | setJoyMode('dark'); 24 | setMaterialMode('dark'); 25 | } else { 26 | setJoyMode('light'); 27 | setMaterialMode('light'); 28 | } 29 | }, [myTheme, setJoyMode, setMaterialMode]); 30 | 31 | return ( 32 | <> 33 | {myAdvancedMedia.advancedMedia.id !== -1 ? ( 34 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ) : ( 55 | 56 | )} 57 | 58 | ); 59 | } 60 | 61 | // title is a 2 liner 62 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/description/AdvancedDescription.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Card, CardContent, Typography } from '@mui/material'; 2 | import Parser from 'html-react-parser'; 3 | import { useTitle } from 'renderer/context/TitleContext'; 4 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 5 | 6 | const AdvancedDescription = () => { 7 | const myAdvancedMedia: any = useAdvancedMedia(); 8 | const titlePreference: any = useTitle(); 9 | 10 | return ( 11 | 21 | 22 | 23 | 24 | {myAdvancedMedia.advancedMedia.description !== null 25 | ? Parser(myAdvancedMedia.advancedMedia.description) 26 | : ''} 27 | 28 | 29 | 30 | 31 | ); 32 | }; 33 | 34 | export default AdvancedDescription; 35 | 36 | /* 37 | 38 | {`Synonyms: ${getOtherTitles( 39 | titlePreference.title, 40 | myAdvancedMedia.advancedMedia 41 | ).map((e: any, index: number) => { 42 | if ( 43 | index + 1 !== 44 | getOtherTitles( 45 | titlePreference.title, 46 | myAdvancedMedia.advancedMedia 47 | ).length && 48 | myAdvancedMedia.advancedMedia.synonyms.length !== 0 49 | ) { 50 | return `${e}, `; 51 | } 52 | return `${e}`; 53 | })}`} 54 | {myAdvancedMedia.advancedMedia.synonyms.map((e: any, index: number) => { 55 | if (index + 1 !== myAdvancedMedia.advancedMedia.synonyms.length) { 56 | return `${e}, `; 57 | } 58 | return `${e}`; 59 | })} 60 | 61 | */ 62 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/entryInput/notOnList/EntryInputNotOnList.tsx: -------------------------------------------------------------------------------- 1 | import { Card, CardContent } from '@mui/material'; 2 | import AddToList from './AddToList'; 3 | 4 | export default function EntryInputNotOnList() { 5 | return ( 6 | 15 | 24 | 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/entryInput/onList/EntryInputOnList.tsx: -------------------------------------------------------------------------------- 1 | import { Card, CardContent } from '@mui/material'; 2 | import { useAdvancedInput } from 'renderer/context/advanced/AdvancedInputContext'; 3 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 4 | import MyDatePickerCompletedAt from './MyDatePickerCompletedAt'; 5 | import MyDatePickerStartedAt from './MyDatePickerStartedAt'; 6 | import NotesInput from './NotesInput'; 7 | import PrivateCheckBox from './PrivateCheckBox'; 8 | import ProgressInput from './ProgressInput'; 9 | import ProgressVolumesInput from './ProgressVolumesInput'; 10 | import RepeatInput from './RepeatInput'; 11 | import ScoreInput from './ScoreInput'; 12 | import StatusSelect from './StatusSelect'; 13 | import UpdateButton from './UpdateButton'; 14 | 15 | export default function EntryInputOnList() { 16 | const myAdvancedMedia: any = useAdvancedMedia(); 17 | const myAdvancedInput: any = useAdvancedInput(); 18 | 19 | return ( 20 | 29 | 40 | 41 | {myAdvancedMedia.advancedMedia.type === 'MANGA' ? ( 42 | 43 | ) : null} 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ); 55 | } 56 | 57 | // 58 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/entryInput/onList/JoyDatePicker.tsx: -------------------------------------------------------------------------------- 1 | import Input from '@mui/joy/Input'; 2 | import Stack from '@mui/joy/Stack'; 3 | 4 | export default function JoyDatePicker() { 5 | return ( 6 | 7 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/entryInput/onList/MyDatePicker.tsx: -------------------------------------------------------------------------------- 1 | import { Box } from '@mui/material'; 2 | import { DesktopDatePicker, LocalizationProvider } from '@mui/x-date-pickers'; 3 | import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; 4 | import { DemoContainer, DemoItem } from '@mui/x-date-pickers/internals/demo'; 5 | import dayjs from 'dayjs'; 6 | import { useAdvancedInput } from 'renderer/context/advanced/AdvancedInputContext'; 7 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 8 | 9 | export default function MyDatePicker({ props }: any) { 10 | const myMediaAdvanced: any = useAdvancedMedia(); 11 | const myAdvancedInput: any = useAdvancedInput(); 12 | 13 | const onChange = (e: any) => { 14 | console.log(myAdvancedInput.advancedInput.startedAt); 15 | console.log(e.year()); 16 | console.log(e.month() + 1); 17 | console.log(e.date()); 18 | 19 | myAdvancedInput.dispatch({ 20 | type: 'updateStartedAt', 21 | payload: { year: e.year(), month: e.month() + 1, day: e.date() }, 22 | }); 23 | }; 24 | 25 | return ( 26 | 27 | 28 | 29 | 30 | 37 | 38 | 39 | 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/entryInput/onList/PrivateCheckBox.tsx: -------------------------------------------------------------------------------- 1 | import { useAdvancedInput } from 'renderer/context/advanced/AdvancedInputContext'; 2 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 3 | import Box from '@mui/joy/Box'; 4 | import Checkbox from '@mui/joy/Checkbox'; 5 | import { FormControl, FormLabel } from '@mui/joy'; 6 | 7 | export default function PrivateCheckBox() { 8 | const myAdvancedMedia: any = useAdvancedMedia(); 9 | const myAdvancedInput: any = useAdvancedInput(); 10 | 11 | const onClick = (e: any) => { 12 | myAdvancedInput.dispatch({ 13 | type: 'updatePrivate', 14 | payload: !myAdvancedInput.advancedInput.private, 15 | }); 16 | }; 17 | 18 | return ( 19 | 27 | 28 | 29 | Private: 30 | 31 | 38 | 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/entryInput/onList/PrivateCheckBoxAlt.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox, FormControlLabel, FormGroup } from '@mui/material'; 2 | import { useAdvancedInput } from 'renderer/context/advanced/AdvancedInputContext'; 3 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 4 | 5 | export default function PrivateCheckBoxAlt() { 6 | const myAdvancedMedia: any = useAdvancedMedia(); 7 | const myAdvancedInput: any = useAdvancedInput(); 8 | 9 | const onClick = (e: any) => { 10 | myAdvancedInput.dispatch({ 11 | type: 'updatePrivate', 12 | payload: !myAdvancedInput.advancedInput.private, 13 | }); 14 | }; 15 | 16 | return ( 17 | 21 | 24 | } 25 | onClick={onClick} 26 | sx={{ alignSelf: 'start', margin: 0 }} 27 | checked={myAdvancedInput.advancedInput.private} 28 | label="Private:" 29 | labelPlacement="top" 30 | /> 31 | 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/entryInput/onList/ScoreInput.tsx: -------------------------------------------------------------------------------- 1 | import { FormControl, FormLabel, Input } from '@mui/joy'; 2 | import { useAdvancedInput } from 'renderer/context/advanced/AdvancedInputContext'; 3 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 4 | 5 | export default function ScoreInput() { 6 | const myAdvancedMedia: any = useAdvancedMedia(); 7 | const myAdvancedInput: any = useAdvancedInput(); 8 | 9 | const onChange = (e: any) => { 10 | const value = e.target.value 11 | .replace(/[^0-9.]+/g, '') 12 | .replace(/^(?:0+(?=[1-9])|0+(?=0$))/gm, ''); // removes all leading 0's except 0 13 | console.log(parseFloat(value).toFixed(1) || 0); 14 | 15 | const maxValue = 10; 16 | let isMaxNull = false; 17 | if (maxValue === null) { 18 | isMaxNull = true; 19 | } 20 | if (isMaxNull) { 21 | if (parseFloat(value) > 10) { 22 | myAdvancedInput.dispatch({ 23 | type: 'updateScore', 24 | payload: 10, 25 | }); 26 | } else { 27 | myAdvancedInput.dispatch({ 28 | type: 'updateScore', 29 | payload: value, // leave it like this 30 | }); 31 | } 32 | } 33 | if (!isMaxNull) { 34 | if (parseFloat(value) > maxValue) { 35 | myAdvancedInput.dispatch({ 36 | type: 'updateScore', 37 | payload: maxValue, 38 | }); 39 | } else { 40 | myAdvancedInput.dispatch({ 41 | type: 'updateScore', 42 | payload: value, // leave it like this 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | return ( 49 | 50 | Score: 51 | 56 | ['e', 'E', '+', '-'].includes(evt.key) && evt.preventDefault() 57 | } 58 | slotProps={{ 59 | input: { 60 | min: 0, 61 | max: 10, 62 | step: 0.1, 63 | }, 64 | }} 65 | sx={{ marginRight: '10px' }} 66 | onChange={onChange} 67 | /> 68 | 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/extra/AdvancedExtra.tsx: -------------------------------------------------------------------------------- 1 | import { Box } from '@mui/material'; 2 | import { useTheme } from 'renderer/context/ThemeContext'; 3 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 4 | import { useAtomValue } from 'jotai'; 5 | import { infoTypeAtom } from 'renderer/store'; 6 | import ThemeSongButton from './ThemeSongButton'; 7 | import TrailerButton from './TrailerButton'; 8 | import AdvancedExtraSelect from './AdvancedExtraSelect'; 9 | 10 | const ButtonBox = () => { 11 | const infoType = useAtomValue(infoTypeAtom); 12 | if (infoType === 1) { 13 | return ; 14 | } 15 | if (infoType === 2) { 16 | return ; 17 | } 18 | return ; 19 | }; 20 | 21 | export default function AdvancedExtra({ props }: any) { 22 | const myMediaAdvanced: any = useAdvancedMedia(); 23 | const myTheme: any = useTheme(); 24 | 25 | return ( 26 | 37 | 38 | {/* myMediaAdvanced.advancedMedia.type === 'ANIME' ? ( 39 | 40 | ) : null 41 | 42 | */} 43 | 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/extra/AlternativeLink.tsx: -------------------------------------------------------------------------------- 1 | import OpenInNewIcon from '@mui/icons-material/OpenInNew'; 2 | import { IconButton, Tooltip } from '@mui/material'; 3 | import { useAdvancedDefaultLink } from 'renderer/context/advanced/AdvancedDefaultLinkContext'; 4 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 5 | import { getMalLink } from 'renderer/functions/edit/getAdjustedSiteLink'; 6 | 7 | export default function AlternativeLink({ props }: any) { 8 | const myAdvancedMedia: any = useAdvancedMedia(); 9 | const myAdvancedDefaultLink: any = useAdvancedDefaultLink(); 10 | 11 | const handleOnClick = () => { 12 | if (myAdvancedDefaultLink.advancedDefaultLink === 'MyAnimeList') { 13 | // AniList 14 | window.electron.ipcRenderer.sendMessage('openExternalLink', [ 15 | myAdvancedMedia.advancedMedia.siteUrl, 16 | ]); 17 | } else { 18 | // MyAnimeList 19 | window.electron.ipcRenderer.sendMessage('openExternalLink', [ 20 | getMalLink( 21 | myAdvancedMedia.advancedMedia.idMal, 22 | myAdvancedMedia.advancedMedia.type, 23 | ), 24 | ]); 25 | } 26 | }; 27 | 28 | return ( 29 | 36 | 37 | 38 | 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/extra/DeleteButton.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Button } from '@mui/joy'; 2 | import React from 'react'; 3 | import DeleteIcon from '@mui/icons-material/Delete'; 4 | import { useAtom } from 'jotai'; 5 | import { infoTypeAtom } from 'renderer/store'; 6 | import { useAniListUsername } from 'renderer/context/services/AniListUsernameContext'; 7 | import { useAniListToken } from 'renderer/context/services/AniListTokenContext'; 8 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 9 | import { useDeleteEntryData } from 'renderer/functions/api/mutations/deleteEntry'; 10 | import { useAdvancedInput } from 'renderer/context/advanced/AdvancedInputContext'; 11 | 12 | const DeleteButton = () => { 13 | const [infoType, setInfoType] = useAtom(infoTypeAtom); 14 | const myUserName: any = useAniListUsername(); 15 | const myToken: any = useAniListToken(); 16 | const myAdvancedMedia: any = useAdvancedMedia(); 17 | const deleteMutation: any = useDeleteEntryData(); 18 | const myAdvancedInput: any = useAdvancedInput(); 19 | const onClick = () => { 20 | setInfoType(0); 21 | console.log('deleted'); 22 | const entry: any = { 23 | myUserName: myUserName.AniListUsername, 24 | myToken: myToken.AniListToken, 25 | myMediaId: myAdvancedMedia.advancedMedia.id, 26 | mediaListEntry: myAdvancedInput.advancedInput, 27 | advancedMedia: myAdvancedMedia.advancedMedia, 28 | }; 29 | deleteMutation.mutate(entry); 30 | }; 31 | 32 | return ( 33 | 40 | 44 | 45 | ); 46 | }; 47 | 48 | export default DeleteButton; 49 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/extra/InfoButton.tsx: -------------------------------------------------------------------------------- 1 | import { IconButton, Tooltip } from '@mui/material'; 2 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 3 | 4 | import InfoIcon from '@mui/icons-material/Info'; 5 | import { useAdvancedMoreInfo } from 'renderer/context/advanced/AdvancedMoreInfoContext'; 6 | 7 | export default function InfoButton({ props }: any) { 8 | const myMediaAdvanced: any = useAdvancedMedia(); 9 | const advancedMoreInfo: any = useAdvancedMoreInfo(); 10 | 11 | const handleOnClick = () => { 12 | console.log('more info'); 13 | advancedMoreInfo.setAdvancedMoreInfo(!advancedMoreInfo.advancedMoreInfo); 14 | }; 15 | 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/extra/ThemeSongButton.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Tooltip, Typography } from '@mui/material'; 2 | import MusicVideoIcon from '@mui/icons-material/MusicVideo'; 3 | import axios from 'axios'; 4 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 5 | import { useState } from 'react'; 6 | import { useAdvancedThemeSongs } from 'renderer/context/advanced/AdvancedThemeSongContext'; 7 | import { Button } from '@mui/joy'; 8 | 9 | export default function ThemeSongButton({ props }: any) { 10 | const myMediaAdvanced: any = useAdvancedMedia(); 11 | const { advancedThemeSongs, setAdvancedThemeSongs }: any = 12 | useAdvancedThemeSongs(); 13 | const getData = async () => { 14 | const { data } = await axios.get( 15 | `https://api.jikan.moe/v4/anime/${myMediaAdvanced.advancedMedia.idMal}/themes`, 16 | ); 17 | console.log(data); 18 | setAdvancedThemeSongs(data.data); 19 | }; 20 | 21 | const handleOnClick = async () => { 22 | getData(); 23 | }; 24 | 25 | return ( 26 | 27 | 28 | 37 | 38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/extra/TrailerButton.tsx: -------------------------------------------------------------------------------- 1 | import YouTubeIcon from '@mui/icons-material/YouTube'; 2 | import { Button, Typography } from '@mui/joy'; 3 | import { Link } from 'react-router-dom'; 4 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 5 | 6 | export default function TrailerButton({ props }: any) { 7 | const myMediaAdvanced: any = useAdvancedMedia(); 8 | 9 | return ( 10 | 18 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedInformationDelete.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import { Box } from '@mui/material'; 3 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 4 | import DeleteButton from '../extra/DeleteButton'; 5 | 6 | const AdvancedInformationDelete = () => { 7 | const myAdvancedMedia: any = useAdvancedMedia(); 8 | 9 | const textGenresRef: any = useState(null); 10 | 11 | const [isOverflowedGenres, setIsOverflowGenres] = useState(false); 12 | 13 | useEffect(() => { 14 | setIsOverflowGenres( 15 | textGenresRef?.current?.scrollWidth > textGenresRef?.current?.clientWidth, 16 | ); 17 | }, [textGenresRef, myAdvancedMedia]); 18 | 19 | const textStudioRef: any = useState(null); 20 | 21 | const [isOverflowedStudio, setIsOverflowStudio] = useState(false); 22 | 23 | useEffect(() => { 24 | setIsOverflowStudio( 25 | textStudioRef?.current?.scrollWidth > textStudioRef?.current?.clientWidth, 26 | ); 27 | }, [textStudioRef, myAdvancedMedia]); 28 | 29 | const textTagsRef: any = useState(null); 30 | 31 | const [isOverflowedTags, setIsOverflowTags] = useState(false); 32 | 33 | useEffect(() => { 34 | setIsOverflowTags( 35 | textTagsRef?.current?.scrollWidth > textTagsRef?.current?.clientWidth, 36 | ); 37 | }, [textTagsRef, myAdvancedMedia]); 38 | 39 | return ( 40 | 41 | 42 | 43 | ); 44 | }; 45 | 46 | export default AdvancedInformationDelete; 47 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedInformationTrailer.tsx: -------------------------------------------------------------------------------- 1 | import { Box } from '@mui/material'; 2 | import React from 'react'; 3 | import TrailerButton from '../extra/TrailerButton'; 4 | 5 | const AdvancedInformationTrailer = () => { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | }; 12 | 13 | export default AdvancedInformationTrailer; 14 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedMediaAverageScore.tsx: -------------------------------------------------------------------------------- 1 | export default function AdvancedMediaAverageScore() { 2 | return
AdvancedMediaAverageScore
; 3 | } 4 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedMediaGenres.tsx: -------------------------------------------------------------------------------- 1 | export default function AdvancedMediaGenres() { 2 | return
AdvancedMediaGenres
; 3 | } 4 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedMediaSeason.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function AdvancedMediaSeason() { 4 | return
AdvancedMediaSeason
; 5 | } 6 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedMediaStatus.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function AdvancedMediaStatus() { 4 | return
AdvancedMediaStatus
; 5 | } 6 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedMediaStudio.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function AdvancedMediaStudio() { 4 | return
AdvancedMediaStudio
; 5 | } 6 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedMediaSynonyms.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function AdvancedMediaSynonyms() { 4 | return
AdvancedMediaSynonyms
; 5 | } 6 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedMediaThemes.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function AdvancedMediaThemes() { 4 | return
AdvancedMediaThemes
; 5 | } 6 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/information/AdvancedMediaType.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function AdvancedMediaType() { 4 | return
AdvancedMediaType
; 5 | } 6 | -------------------------------------------------------------------------------- /src/renderer/components/mediaAdvanced/title/AdvancedTitle.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip } from '@mui/joy'; 2 | import { Card, CardContent, Typography } from '@mui/material'; 3 | import { useEffect, useState } from 'react'; 4 | import { useTitle } from 'renderer/context/TitleContext'; 5 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 6 | import { getTitle } from 'renderer/functions/view/TitlePreferenceFunctions'; 7 | 8 | export default function AdvancedTitle() { 9 | const myAdvancedMedia: any = useAdvancedMedia(); 10 | const titlePreference: any = useTitle(); 11 | const textElementRef: any = useState(null); 12 | 13 | const [isOverflowed, setIsOverflow] = useState(false); 14 | 15 | useEffect(() => { 16 | setIsOverflow( 17 | textElementRef?.current?.scrollWidth > 18 | textElementRef?.current?.clientWidth, 19 | ); 20 | }, [textElementRef, myAdvancedMedia]); 21 | 22 | return ( 23 | 32 | 33 | 41 | 47 | {getTitle(titlePreference.title, myAdvancedMedia.advancedMedia)} 48 | 49 | 50 | 51 | 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /src/renderer/components/settings/TestButton.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@mui/material'; 2 | 3 | export default function TestButton() { 4 | return ( 5 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/renderer/components/settings/app/AdultLabel.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Checkbox, FormControlLabel, FormGroup } from '@mui/material'; 2 | import { useAdult } from 'renderer/context/AdultContext'; 3 | import { useAniListToken } from 'renderer/context/services/AniListTokenContext'; 4 | import { useAniListUsername } from 'renderer/context/services/AniListUsernameContext'; 5 | import { getUser } from 'renderer/functions/UserFunctions'; 6 | 7 | function AdultLabel() { 8 | const adult: any = useAdult(); 9 | const myToken: any = useAniListToken(); 10 | const myUsername: any = useAniListUsername(); 11 | 12 | const handleChange = async (event: any) => { 13 | await adult.setAdult(event.target.checked); 14 | if (event.target.checked) { 15 | window.electron.ipcRenderer.sendMessage('adultFlag', [ 16 | event.target.checked, 17 | ]); 18 | console.log(adult); 19 | console.log(event.target.checked); 20 | console.log( 21 | getUser({ 22 | username: myUsername.AniListUsername, 23 | myToken: myToken.AniListToken, 24 | adult: true, 25 | }), 26 | ); 27 | /* console.log( 28 | changeUserAdult({ 29 | username: myUsername.AniListUsername, 30 | myToken: myToken.AniListToken, 31 | adult: true, 32 | }), 33 | ); */ 34 | } 35 | if (!event.target.checked) { 36 | window.electron.ipcRenderer.sendMessage('adultFlag', [ 37 | event.target.checked, 38 | ]); 39 | console.log(event.target.checked); 40 | console.log( 41 | getUser({ 42 | username: myUsername.AniListUsername, 43 | myToken: myToken.AniListToken, 44 | adult: true, 45 | }), 46 | ); 47 | /* console.log( 48 | changeUserAdult({ 49 | username: myUsername.AniListUsername, 50 | myToken: myToken.AniListToken, 51 | adult: false, 52 | }), 53 | ); */ 54 | } 55 | }; 56 | 57 | return ( 58 | 59 | 60 | } 62 | label="18+ Content" 63 | onChange={handleChange} 64 | /> 65 | 66 | 67 | ); 68 | } 69 | 70 | export default AdultLabel; 71 | -------------------------------------------------------------------------------- /src/renderer/components/settings/app/DefaultStatus.tsx: -------------------------------------------------------------------------------- 1 | import { Box, FormControl, InputLabel, NativeSelect } from '@mui/material'; 2 | import { useAtom } from 'jotai'; 3 | import React from 'react'; 4 | import { statusAddSelectAtom } from 'renderer/store'; 5 | 6 | const DefaultStatus = () => { 7 | const [defaultAddStatus, setDefaultAddStatus] = useAtom(statusAddSelectAtom); 8 | 9 | const handleChange = (event: any) => { 10 | console.log(event.target.value); 11 | setDefaultAddStatus(event.target.value); 12 | window.electron.store.set('defaultAddStatus', event.target.value); 13 | window.electron.ipcRenderer.sendMessage('updateMainFromSettings', [ 14 | 'addStatus', 15 | event.target.value, 16 | ]); 17 | }; 18 | 19 | return ( 20 | 21 | 22 | 23 | Add To List 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ); 39 | }; 40 | 41 | export default DefaultStatus; 42 | -------------------------------------------------------------------------------- /src/renderer/components/settings/app/NextAiringEpisodeMainList.tsx: -------------------------------------------------------------------------------- 1 | import { Box, FormControl, InputLabel, NativeSelect } from '@mui/material'; 2 | import { useAtom } from 'jotai'; 3 | import React from 'react'; 4 | import { nextAiringEpisodeAtom } from 'renderer/store'; 5 | 6 | function NextAiringEpisodeMainList() { 7 | const [nextAiringEpisode, setNextAiringEpisode] = useAtom( 8 | nextAiringEpisodeAtom, 9 | ); 10 | 11 | const handleChange = (event: any) => { 12 | setNextAiringEpisode(event.target.value as string); 13 | window.electron.store.set('nextAiringEpisode', event.target.value); 14 | window.electron.ipcRenderer.sendMessage('updateMainFromSettings', [ 15 | 'nextAiringEpisode', 16 | event.target.value, 17 | ]); 18 | }; 19 | 20 | return ( 21 | 22 | 23 | 24 | Next Airing Episode (Main List) 25 | 26 | 31 | 32 | 33 | 34 | 35 | 36 | ); 37 | } 38 | 39 | export default NextAiringEpisodeMainList; 40 | -------------------------------------------------------------------------------- /src/renderer/components/settings/app/SelectDefaultLink.tsx: -------------------------------------------------------------------------------- 1 | import { Box, FormControl, InputLabel, NativeSelect } from '@mui/material'; 2 | import React from 'react'; 3 | import { useAdvancedDefaultLink } from 'renderer/context/advanced/AdvancedDefaultLinkContext'; 4 | 5 | function SelectDefaultLink() { 6 | const myAdvancedDefaultLink: any = useAdvancedDefaultLink(); 7 | 8 | const handleChange = (event: any) => { 9 | myAdvancedDefaultLink.setAdvancedDefaultLink(event.target.value as string); 10 | window.electron.store.set('defaultLink', event.target.value); 11 | window.electron.ipcRenderer.sendMessage('updateMainFromSettings', [ 12 | 'defaultLink', 13 | event.target.value, 14 | ]); 15 | }; 16 | 17 | return ( 18 | 19 | 20 | 21 | Image Links 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | ); 34 | } 35 | 36 | export default SelectDefaultLink; 37 | -------------------------------------------------------------------------------- /src/renderer/components/settings/app/SelectDefaultSeasonsSort.tsx: -------------------------------------------------------------------------------- 1 | import { Box, FormControl, InputLabel, NativeSelect } from '@mui/material'; 2 | import { useAtom } from 'jotai'; 3 | import React from 'react'; 4 | import { defaultSeasonSortAtom } from 'renderer/store'; 5 | 6 | function SelectDefaultSeasonsSort() { 7 | const [defaultSeasonSort, setDefaultSeasonSort] = useAtom( 8 | defaultSeasonSortAtom, 9 | ); 10 | 11 | const handleChange = (event: any) => { 12 | setDefaultSeasonSort(Number(event.target.value)); 13 | window.electron.store.set('defaultSeasonSort', Number(event.target.value)); 14 | /* 15 | window.electron.ipcRenderer.sendMessage('updateMainFromSettings', [ 16 | 'defaultSeasonSort', 17 | event.target.value, 18 | ]); 19 | */ 20 | }; 21 | 22 | return ( 23 | 24 | 25 | Seasonal Sort 26 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | ); 41 | } 42 | 43 | export default SelectDefaultSeasonsSort; 44 | -------------------------------------------------------------------------------- /src/renderer/components/settings/app/SelectDefaultView.tsx: -------------------------------------------------------------------------------- 1 | import { Box, FormControl, InputLabel, NativeSelect } from '@mui/material'; 2 | import React from 'react'; 3 | import { useMainView } from 'renderer/context/MainViewContext'; 4 | 5 | const SelectDefaultView = () => { 6 | const myMainView: any = useMainView(); 7 | 8 | const handleChange = (event: any) => { 9 | myMainView.setView(event.target.value); 10 | window.electron.store.set('defaultView', Number(event.target.value)); 11 | }; 12 | 13 | return ( 14 | 15 | 16 | 17 | List View Type 18 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | }; 32 | 33 | export default SelectDefaultView; 34 | -------------------------------------------------------------------------------- /src/renderer/components/settings/app/SelectSeasonChange.tsx: -------------------------------------------------------------------------------- 1 | import { Box, FormControl, InputLabel, NativeSelect } from '@mui/material'; 2 | import { useAtom } from 'jotai'; 3 | import React from 'react'; 4 | import { seasonChangeAtom } from 'renderer/store'; 5 | 6 | function SelectSeasonChange() { 7 | const [seasonChange, setSeasonChange] = useAtom(seasonChangeAtom); 8 | 9 | const handleChange = (event: any) => { 10 | setSeasonChange(event.target.value as string); 11 | window.electron.store.set('seasonChange', event.target.value); 12 | window.electron.ipcRenderer.sendMessage('updateMainFromSettings', [ 13 | 'seasonChange', 14 | event.target.value, 15 | ]); 16 | }; 17 | 18 | return ( 19 | 20 | 21 | 22 | Season Change 23 | 24 | 29 | 30 | 33 | 34 | 35 | 36 | ); 37 | } 38 | 39 | export default SelectSeasonChange; 40 | -------------------------------------------------------------------------------- /src/renderer/components/settings/etc/CardContentPaddingAdjusted.tsx: -------------------------------------------------------------------------------- 1 | import { CardContent, styled } from '@mui/material'; 2 | 3 | const CardContentPaddingAdjusted = styled(CardContent)(` 4 | &:last-child { 5 | padding-bottom: 10px; 6 | } 7 | `); 8 | 9 | export default CardContentPaddingAdjusted; 10 | -------------------------------------------------------------------------------- /src/renderer/components/settings/etc/CustomSettingsTooltip.tsx: -------------------------------------------------------------------------------- 1 | import { styled } from '@mui/material'; 2 | import Tooltip, { TooltipProps, tooltipClasses } from '@mui/material/Tooltip'; 3 | 4 | const CustomSettingsTooltip = styled( 5 | ({ className, ...props }: TooltipProps) => ( 6 | // eslint-disable-next-line react/jsx-props-no-spreading 7 | 8 | ), 9 | )(({ theme }) => ({ 10 | [`& .${tooltipClasses.tooltip}`]: { 11 | backgroundColor: '#0b0d0e', 12 | color: '#86b9db', // #86b9db 13 | fontSize: theme.typography.pxToRem(12), 14 | border: '1px solid #4383ce', // #4383ce 15 | maxWidth: 450, 16 | }, 17 | })); 18 | 19 | export default CustomSettingsTooltip; 20 | -------------------------------------------------------------------------------- /src/renderer/components/settings/etc/SaveButton.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Button } from '@mui/material'; 3 | 4 | export default function SaveButton() { 5 | const handleClickOpen = () => { 6 | window.electron.store.set('aniListUsername', 'ReStart'); 7 | window.electron.store.set('aniListToken', 'test'); 8 | }; 9 | 10 | return ( 11 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/renderer/components/settings/etc/SubmitButton.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@mui/material'; 2 | 3 | export default function SubmitButton() { 4 | const handleClickOpen = () => { 5 | console.log('test'); 6 | }; 7 | 8 | return ( 9 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/renderer/components/settings/lang/SelectLanguage.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Box from '@mui/material/Box'; 3 | import InputLabel from '@mui/material/InputLabel'; 4 | import FormControl from '@mui/material/FormControl'; 5 | import { useTitle } from 'renderer/context/TitleContext'; 6 | import { NativeSelect } from '@mui/material'; 7 | 8 | export default function SelectLanguage() { 9 | const [age, setAge] = React.useState(''); 10 | const titlePreference: any = useTitle(); 11 | 12 | const handleChange = (event: any) => { 13 | titlePreference.setTitle(event.target.value as string); 14 | window.electron.store.set('titlePreference', event.target.value); 15 | window.electron.ipcRenderer.sendMessage('updateMainFromSettings', [ 16 | 'titlePreference', 17 | event.target.value, 18 | ]); 19 | }; 20 | 21 | return ( 22 | 23 | 24 | 25 | Title Language 26 | 27 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /src/renderer/components/settings/services/ResetLoginButton.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Button } from '@mui/material'; 3 | 4 | export default function ResetLoginButton() { 5 | const handleClickOpen = () => { 6 | window.electron.ipcRenderer.sendMessage('resetLogin', ['ping']); 7 | }; 8 | 9 | return ( 10 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/renderer/components/settings/services/SelectList.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Box from '@mui/material/Box'; 3 | import InputLabel from '@mui/material/InputLabel'; 4 | import MenuItem from '@mui/material/MenuItem'; 5 | import FormControl from '@mui/material/FormControl'; 6 | import Select, { SelectChangeEvent } from '@mui/material/Select'; 7 | import { useNewsServiceType } from 'renderer/context/NewsServiceTypeContext'; 8 | 9 | export default function SelectList() { 10 | const newsServiceType: any = useNewsServiceType(); 11 | const handleChange = async (event: SelectChangeEvent) => { 12 | console.log('test'); 13 | }; 14 | 15 | return ( 16 | 17 | 18 | List 19 | 29 | 30 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /src/renderer/components/settings/services/SelectNews.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Box from '@mui/material/Box'; 3 | import InputLabel from '@mui/material/InputLabel'; 4 | import MenuItem from '@mui/material/MenuItem'; 5 | import FormControl from '@mui/material/FormControl'; 6 | import Select, { SelectChangeEvent } from '@mui/material/Select'; 7 | import { useNewsServiceType } from 'renderer/context/NewsServiceTypeContext'; 8 | 9 | export default function SelectNews() { 10 | const newsServiceType: any = useNewsServiceType(); 11 | const handleChange = async (event: SelectChangeEvent) => { 12 | await newsServiceType.toggleNews(); 13 | if (event.target.value === 'MyAnimeList') { 14 | window.electron.ipcRenderer.sendMessage('changeNews', [true]); 15 | } 16 | if (event.target.value === 'AnimeNewsNetwork') { 17 | window.electron.ipcRenderer.sendMessage('changeNews', [false]); 18 | } 19 | }; 20 | 21 | return ( 22 | 23 | 24 | News 25 | 36 | 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /src/renderer/components/settings/services/TokenButton.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@mui/material'; 2 | 3 | export default function TokenButton() { 4 | const handleClickOpen = () => { 5 | console.log('test'); 6 | }; 7 | const authLink = `https://anilist.co/api/v2/oauth/authorize?client_id=9413&response_type=token`; 8 | 9 | return ( 10 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /src/renderer/components/settings/services/TokenInput.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Box from '@mui/material/Box'; 3 | import { Input } from '@mui/material'; 4 | 5 | const ariaLabel = { 'aria-label': 'description' }; 6 | 7 | export default function TokenInput() { 8 | return ( 9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/renderer/components/settings/services/UsernameInput.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Box from '@mui/material/Box'; 3 | import { Input } from '@mui/material'; 4 | 5 | const ariaLabel = { 'aria-label': 'description' }; 6 | 7 | export default function UsernameInput() { 8 | return ( 9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/renderer/components/settings/theme/SelectTheme.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Box from '@mui/material/Box'; 3 | import InputLabel from '@mui/material/InputLabel'; 4 | import MenuItem from '@mui/material/MenuItem'; 5 | import FormControl from '@mui/material/FormControl'; 6 | import Select, { SelectChangeEvent } from '@mui/material/Select'; 7 | 8 | export default function SelectTheme() { 9 | const [age, setAge] = React.useState(''); 10 | 11 | const handleChange = (event: SelectChangeEvent) => { 12 | setAge(event.target.value as string); 13 | }; 14 | 15 | return ( 16 | 17 | 18 | Theme 19 | 29 | 30 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /src/renderer/components/trailer/MyTrailer.tsx: -------------------------------------------------------------------------------- 1 | import { useAdvancedMedia } from 'renderer/context/advanced/AdvancedMediaContext'; 2 | import 'renderer/styles/Trailer.scss'; 3 | 4 | export default function MyTrailer({ props }: any) { 5 | const myAdvancedMedia: any = useAdvancedMedia(); 6 | 7 | if (myAdvancedMedia.advancedMedia.trailer.site === 'youtube') { 8 | return ( 9 |