diff options
author | GeckoEidechse <gecko.eidechse+git@pm.me> | 2024-12-22 23:55:52 +0100 |
---|---|---|
committer | GeckoEidechse <gecko.eidechse+git@pm.me> | 2024-12-22 23:55:52 +0100 |
commit | f1dee718da95836ffa5c0985c9e8f5643e0f3f6f (patch) | |
tree | 24967a28bcae1fc1e5b08da9f58bcc678ed52937 /src-vue/src/views | |
parent | cc5ae684221d3165479d7a68556a2bb6fa81cf3a (diff) | |
download | FlightCore-f1dee718da95836ffa5c0985c9e8f5643e0f3f6f.tar.gz FlightCore-f1dee718da95836ffa5c0985c9e8f5643e0f3f6f.zip |
dev: Replace with sample Tauri 2.0 project
as a first step to convert FlightCore to Tauri 2.0
Diffstat (limited to 'src-vue/src/views')
-rw-r--r-- | src-vue/src/views/ChangelogView.vue | 82 | ||||
-rw-r--r-- | src-vue/src/views/DeveloperView.vue | 369 | ||||
-rw-r--r-- | src-vue/src/views/ModsView.vue | 54 | ||||
-rw-r--r-- | src-vue/src/views/PlayView.vue | 124 | ||||
-rw-r--r-- | src-vue/src/views/RepairView.vue | 153 | ||||
-rw-r--r-- | src-vue/src/views/SettingsView.vue | 393 | ||||
-rw-r--r-- | src-vue/src/views/mods/LocalModsView.vue | 72 | ||||
-rw-r--r-- | src-vue/src/views/mods/ThunderstoreModsView.vue | 309 |
8 files changed, 0 insertions, 1556 deletions
diff --git a/src-vue/src/views/ChangelogView.vue b/src-vue/src/views/ChangelogView.vue deleted file mode 100644 index f75d869c..00000000 --- a/src-vue/src/views/ChangelogView.vue +++ /dev/null @@ -1,82 +0,0 @@ -<template> - <div class="fc-container"> - <div v-if="releases.length === 0" class="fc__changelog__container"> - <el-progress :show-text="false" :percentage="50" :indeterminate="true" /> - </div> - <el-scrollbar v-else> - <el-timeline> - <el-timeline-item - v-for="release in releases" - v-bind:key="release.name" - :timestamp="formatDate(release.published_at)" - placement="top" - > - <el-card> - <h4>{{ release.name }}</h4> - <p v-html="formatRelease(release.body)"></p> - </el-card> - </el-timeline-item> - </el-timeline> - </el-scrollbar> - </div> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import { ReleaseInfo } from "../../../src-tauri/bindings/ReleaseInfo"; -import { marked } from "marked"; - - -export default defineComponent({ - name: "ChangelogView", - async mounted() { - this.$store.commit('fetchReleaseNotes'); - }, - computed: { - releases(): ReleaseInfo[] { - return this.$store.state.releaseNotes; - } - }, - methods: { - // Transforms a Markdown document into an HTML document. - // Taken from Viper launcher: - // https://github.com/0neGal/viper/blob/5106d9ed409a3cc91a7755f961fab1bf91d8b7fb/src/app/launcher.js#L26 - formatRelease(releaseBody: string) { - // GitHub authors' links formatting - let content: string = releaseBody.replaceAll(/\@(\S+)/g, `<a target="_blank" href="https://github.com/$1">@$1</a>`); - - // PR's links formatting - content = content.replaceAll(/\[(\S*)\#(\S+)\]\(([^)]+)\)/g, `<a target="_blank" href="$3">$1#$2</a>`); - - return marked.parse(content, { breaks: true }); - }, - // Formats an ISO-formatted date into a human-readable string. - formatDate(timestamp: string): string { - return new Date(timestamp).toLocaleDateString(); - } - } -}); -</script> - -<style> -.el-scrollbar__view { - padding: 20px 30px; -} - -.el-table .el-scrollbar__view { - padding: 0; -} - -.fc__changelog__container { - padding: 20px 30px; -} - -.el-timeline-item__timestamp { - color: white !important; - user-select: none !important; -} - -.el-card__body * { - max-width: 100%; -} -</style> diff --git a/src-vue/src/views/DeveloperView.vue b/src-vue/src/views/DeveloperView.vue deleted file mode 100644 index 19214157..00000000 --- a/src-vue/src/views/DeveloperView.vue +++ /dev/null @@ -1,369 +0,0 @@ -<template> - <div class="fc-container"> - <el-scrollbar> - <el-alert title="Warning" type="warning" :closable="false" show-icon> - This page is designed for developers. Some of the buttons here can break your Northstar install if you do not know what you're doing! - </el-alert> - - <h3>Basic:</h3> - - <el-button type="primary" @click="disableDevMode"> - Disable developer mode - </el-button> - - <el-button type="primary" @click="crashApplication"> - Panic button - </el-button> - - <h3>Linux:</h3> - - <el-button type="primary" @click="installNSProton"> - Install NSProton - </el-button> - - <el-button type="primary" @click="uninstallNSProton"> - Remove NSProton - </el-button> - - <el-button type="primary" @click="getLocalNSProtonVersion"> - Get local NSProton Version - </el-button> - - <h3>Testing:</h3> - - <el-button type="primary" @click="launchGameWithoutChecks"> - Launch Northstar (bypass all checks) - </el-button> - - <el-button type="primary" @click="launchGameViaSteam"> - Launch Northstar via Steam - </el-button> - - <el-button type="primary" @click="installLauncherGitMain"> - Install launcher from main branch - </el-button> - - <br /> - <br /> - - <el-button type="primary" @click="getAvailableNorthstarVersions"> - Get available versions - </el-button> - - <el-select v-model="selected_ns_version" class="m-2" placeholder="Versions"> - <el-option - v-for="item in ns_versions" - :key="item.value" - :label="item.label" - :value="item" - /> - </el-select> - - <el-button type="primary" @click="installNorthstarVersion"> - Install - </el-button> - - <h3>Repair:</h3> - - <el-button type="primary" @click="checkCgnat"> - Run tracert and collect hop count - </el-button> - - <el-button type="primary" @click="getInstalledMods"> - Get installed mods - </el-button> - - <h3>Testing</h3> - <pull-requests-selector /> - - <h3>Mod install:</h3> - - <el-input v-model="mod_to_install_field_string" placeholder="Please input Thunderstore dependency string (example: AuthorName-ModName-1.2.3)" clearable /> - - <el-button type="primary" @click="installMod"> - Install mod - </el-button> - - <h3>Release management</h3> - <el-select v-model="selected_project" placeholder="Select"> - <el-option - v-for="item in project" - :key="item.value" - :label="item.label" - :value="item.value" - /> - </el-select> - <el-button type="primary" @click="getTags"> - Get tags - </el-button> - - <el-select v-model="firstTag" class="m-2" placeholder="First tag"> - <el-option - v-for="item in ns_release_tags" - :key="item.value" - :label="item.label" - :value="item" - /> - </el-select> - <el-select v-model="secondTag" class="m-2" placeholder="Second tag"> - <el-option - v-for="item in ns_release_tags" - :key="item.value" - :label="item.label" - :value="item" - /> - </el-select> - - <el-button type="primary" @click="compareTags"> - Compare Tags - </el-button> - - <el-button type="primary" @click="copyReleaseNotesToClipboard"> - Copy to clipboard - </el-button> - - <el-input - v-model="release_notes_text" - type="textarea" - :rows="5" - placeholder="Output" - /> - - <h3>Release announcements</h3> - - <el-button type="primary" @click="generateReleaseAnnouncementMessage"> - Generate release announcement - </el-button> - - <el-input - v-model="discord_release_announcement_text" - type="textarea" - :rows="5" - placeholder="Output" - /> - </el-scrollbar> - </div> -</template> - -<script lang="ts"> -import { defineComponent } from "vue"; -import { invoke } from "@tauri-apps/api"; -import { NorthstarLaunchOptions } from "../../../src-tauri/bindings/NorthstarLaunchOptions"; -import { TagWrapper } from "../../../src-tauri/bindings/TagWrapper"; -import { NorthstarThunderstoreReleaseWrapper } from "../../../src-tauri/bindings/NorthstarThunderstoreReleaseWrapper"; -import PullRequestsSelector from "../components/PullRequestsSelector.vue"; -import { showErrorNotification, showNotification } from "../utils/ui"; -import { Project } from "../../../src-tauri/bindings/Project" - -export default defineComponent({ - name: "DeveloperView", - components: { - PullRequestsSelector - }, - data() { - return { - mod_to_install_field_string: "", - release_notes_text: "", - discord_release_announcement_text: "", - first_tag: { label: '', value: { name: '' } }, - second_tag: { label: '', value: { name: '' } }, - ns_release_tags: [] as TagWrapper[], - ns_versions: [] as NorthstarThunderstoreReleaseWrapper[], - selected_ns_version: { label: '', value: { package: '', version: '' } } as NorthstarThunderstoreReleaseWrapper, - selected_project: "FlightCore", - project: [ - { - value: 'FlightCore', - label: 'FlightCore', - }, - { - value: 'Northstar', - label: 'Northstar', - } - ], - } - }, - computed: { - firstTag: { - get(): TagWrapper { - return this.first_tag; - }, - set(value: TagWrapper) { - this.first_tag = value; - } - }, - secondTag: { - get(): TagWrapper { - return this.second_tag; - }, - set(value: TagWrapper) { - this.second_tag = value; - } - }, - }, - methods: { - disableDevMode() { - this.$store.commit('toggleDeveloperMode'); - }, - async crashApplication() { - await invoke("force_panic"); - showErrorNotification("Never should have been able to get here!"); - }, - async launchGameWithoutChecks() { - let launch_options: NorthstarLaunchOptions = { bypass_checks: true, launch_via_steam: false }; - this.$store.commit('launchGame', launch_options); - }, - async launchGameViaSteam() { - let launch_options: NorthstarLaunchOptions = { bypass_checks: false, launch_via_steam: true }; - this.$store.commit('launchGameSteam', launch_options); - }, - async getInstalledMods() { - await invoke("get_installed_mods_and_properties", { gameInstall: this.$store.state.game_install }).then((message) => { - // Simply console logging for now - // In the future we should display the installed mods somewhere - console.log(message); - - // Just a visual indicator that it worked - showNotification('Success'); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async installMod() { - let mod_to_install = this.mod_to_install_field_string; - await invoke<string>("install_mod_wrapper", { gameInstall: this.$store.state.game_install, thunderstoreModString: mod_to_install }).then((message) => { - // Show user notification if mod install completed. - showNotification(`Installed ${mod_to_install}`, message); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async getTags() { - await invoke<TagWrapper[]>("get_list_of_tags", { project: this.selected_project }) - .then((message) => { - this.ns_release_tags = message; - showNotification("Done", "Fetched tags"); - this.first_tag = this.ns_release_tags[1]; - this.second_tag = this.ns_release_tags[0]; - this.compareTags(); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async compareTags() { - await invoke<string>("compare_tags", { project: this.selected_project, firstTag: this.firstTag.value, secondTag: this.secondTag.value }) - .then((message) => { - this.release_notes_text = message; - showNotification("Done", "Generated release notes"); - this.copyReleaseNotesToClipboard(); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async installLauncherGitMain() { - - const notification = showNotification(`Installing git main`, 'Please wait', 'info', 0); - - await invoke<string>("install_git_main", { gameInstallPath: this.$store.state.game_install.game_path }) - .then((message) => { - this.release_notes_text = message; - showNotification("Done", `Installed launcher build from ${message}`); - }) - .catch((error) => { - showErrorNotification(error); - }) - .finally(() => { - // Clear old notification - notification.close(); - }); - }, - async getAvailableNorthstarVersions() { - await invoke<NorthstarThunderstoreReleaseWrapper[]>("get_available_northstar_versions") - .then((message) => { - this.ns_versions = message; - showNotification("Done", "Fetched all available Northstar versions"); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async installNorthstarVersion() { - // Send notification telling the user to wait for the process to finish - const notification = showNotification( - `Installing Northstar version v${this.selected_ns_version.value.version}`, - "Please wait", - 'info', - 0 - ); - - let install_northstar_result = invoke("install_northstar_wrapper", { gameInstall: this.$store.state.game_install, northstarPackageName: this.selected_ns_version.value.package, versionNumber: this.selected_ns_version.value.version }); - - await install_northstar_result - .then((message) => { - // Send notification - showNotification(this.$t('generic.done'), this.$t('settings.repair.window.reinstall_success')); - this.$store.commit('checkNorthstarUpdates'); - }) - .catch((error) => { - showErrorNotification(error); - console.error(error); - }) - .finally(() => { - // Clear old notification - notification.close(); - }); - }, - async installNSProton() { - showNotification(`Started NSProton install`); - await invoke("install_northstar_proton_wrapper") - .then((message) => { showNotification(`Done`); }) - .catch((error) => { showNotification(`Error`, error, "error"); }) - }, - async uninstallNSProton() { - await invoke("uninstall_northstar_proton_wrapper") - .then((message) => { showNotification(`Done`); }) - .catch((error) => { showNotification(`Error`, error, "error"); }) - }, - async getLocalNSProtonVersion() { - await invoke("get_local_northstar_proton_wrapper_version") - .then((message) => { showNotification(`NSProton Version`, message as string); }) - .catch((error) => { showNotification(`Error`, error, "error"); }) - }, - async checkCgnat() { - await invoke<string>("check_cgnat") - .then((message) => { - showNotification(message); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async copyReleaseNotesToClipboard() { - navigator.clipboard.writeText(this.release_notes_text) - .then(() => { - showNotification("Copied to clipboard"); - }) - .catch(() => { - showErrorNotification("Failed copying to clipboard"); - }); - }, - async generateReleaseAnnouncementMessage() { - await invoke<string>("generate_release_note_announcement", { }) - .then((message) => { - this.discord_release_announcement_text = message; - showNotification("Done", "Generated announcement"); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - } -}); -</script> - -<style scoped> -</style> diff --git a/src-vue/src/views/ModsView.vue b/src-vue/src/views/ModsView.vue deleted file mode 100644 index a821dcda..00000000 --- a/src-vue/src/views/ModsView.vue +++ /dev/null @@ -1,54 +0,0 @@ -<template> - <div class="fc-container" style="display: flex"> - <!-- Local mods/Thunderstore mods menu --> - <mods-menu - :showingLocalMods="show_local_mods" - @showLocalMods="(v) => show_local_mods = v" - /> - - <!-- Mods content --> - <div class="fc_mods__container"> - <local-mods-view - v-if="show_local_mods" - /> - - <thunderstore-mods-view - v-else - clearable - /> - </div> - </div> -</template> - -<script lang="ts"> -import { defineComponent } from "vue"; -import ThunderstoreModsView from "./mods/ThunderstoreModsView.vue"; -import LocalModsView from "./mods/LocalModsView.vue"; -import ModsMenu from "../components/ModsMenu.vue"; - -export default defineComponent({ - name: "ModsView", - components: { - ModsMenu, - LocalModsView, - ThunderstoreModsView - }, - data() { - return { - show_local_mods: true, - } - }, - mounted() { - // Fetch Thunderstore mods to eventually display outdated mods count - this.$store.commit('fetchThunderstoreMods'); - } -}); -</script> - -<style scoped> -.fc_mods__container { - display: flex; - width: 100%; - flex-direction: column; -} -</style> diff --git a/src-vue/src/views/PlayView.vue b/src-vue/src/views/PlayView.vue deleted file mode 100644 index 30171e48..00000000 --- a/src-vue/src/views/PlayView.vue +++ /dev/null @@ -1,124 +0,0 @@ -<script lang="ts"> -import { Tabs } from "../utils/Tabs"; -import PlayButton from '../components/PlayButton.vue'; -import { defineComponent } from "vue"; -import InstallProgressBar from "../components/InstallProgressBar.vue"; - -export default defineComponent({ - components: { - PlayButton, - InstallProgressBar - }, - computed: { - northstarIsRunning(): boolean { - return this.$store.state.northstar_is_running; - }, - northstarVersion(): string { - return this.$store.state.installed_northstar_version; - }, - playerCount(): number { - return this.$store.state.player_count; - }, - serverCount(): number { - return this.$store.state.server_count; - }, - }, - methods: { - showChangelogPage() { - this.$store.commit('updateCurrentTab', Tabs.CHANGELOG); - } - } -}); -</script> - -<template> - <div class="fc_launch__container"> - <div class="fc_title">Northstar</div> - <div class="fc_northstar__version__container"> - {{ northstarVersion === '' ? $t('play.unknown_version') : `v${northstarVersion}` }} - <div v-if="northstarVersion !== ''" class="fc_changelog__link" @click="showChangelogPage"> - ({{ $t('play.see_patch_notes') }}) - </div> - <div v-if="playerCount >= 0" class="fc-stats__container"> - {{ playerCount }} {{ $t('play.players') }}, - {{ serverCount }} {{ $t('play.servers') }} - </div> - <div v-else="playerCount >= 0" class="fc-stats__container"> - {{ $t('play.unable_to_load_playercount') }} - </div> - </div> - - <!-- Align play button and services state container --> - <div style="display: flex"> - <PlayButton /> - <div v-if="$store.state.developer_mode" id="fc_services__status"> - <div> - <div class="fc_version__line">{{ $t('play.northstar_running') }}</div> - <div class="fc_version__line fc_version__line__boolean"> {{ northstarIsRunning }}</div> - </div> - <div> - <div class="fc_version__line">{{ $t('play.ea_app_running') }}</div> - <div class="fc_version__line fc_version__line__boolean">{{ $store.state.origin_is_running }}</div> - </div> - </div> - </div> - <InstallProgressBar /> - </div> -</template> - -<style scoped> -.fc_launch__container { - margin: 50px 50px 30px 50px; - position: fixed; - bottom: 0; -} - -/* Titles */ -.fc_title { - color: white; - font-size: 50px; - font-weight: bold; -} - -/* Northstar version + changelog link */ -.fc_northstar__version__container { - margin-bottom: 20px; - color: rgb(168, 168, 168); -} - -.fc-stats__container { - margin-top: 3px; -} - -.fc_northstar__version, -.fc_changelog__link { - display: inline-block; -} - -.fc_changelog__link { - margin-left: 3px; - text-decoration: underline; - cursor: pointer; -} - - -.fc_launch__button:focus { - background-color: var(--el-color-primary); - border-color: var(--el-color-primary); -} - -#fc_services__status { - color: #e8edef; - align-self: end; -} - -.fc_version__line { - display: inline-block; -} - -.fc_version__line__boolean { - margin-left: 5px; - margin-bottom: 5px; - color: #b4b6b9; -} -</style> diff --git a/src-vue/src/views/RepairView.vue b/src-vue/src/views/RepairView.vue deleted file mode 100644 index 341dff2d..00000000 --- a/src-vue/src/views/RepairView.vue +++ /dev/null @@ -1,153 +0,0 @@ -<template> - <div class="fc-container"> - <el-scrollbar> - <el-alert :title="$t('generic.informationShort')" type="info" :closable="false" show-icon> - {{ $t('settings.repair.window.warning') }} - </el-alert> - - <h1>{{ $t('settings.repair.title') }}</h1> - - <h2>Northstar</h2> - - <el-button type="primary" @click="disableAllModsButCore"> - {{ $t('settings.repair.window.disable_all_but_core') }} - </el-button> - - <el-button type="primary" @click="forceInstallNorthstar"> - {{ $t('settings.repair.window.force_reinstall_ns') }} - </el-button> - - <el-button type="primary" @click="killNorthstar"> - {{ $t('settings.repair.window.kill_northstar_process') }} - </el-button> - - <el-button type="primary" @click="disableModsettingsMod"> - {{ $t('settings.repair.window.disable_modsettings') }} - </el-button> - - <h2>FlightCore</h2> - - <el-button type="primary" @click="cleanUpDownloadFolder"> - {{ $t('settings.repair.window.force_delete_temp_dl') }} - </el-button> - - <el-button type="primary" @click="clearFlightCorePersistentStore"> - {{ $t('settings.repair.window.delete_persistent_store') }} - </el-button> - </el-scrollbar> - </div> -</template> - -<script lang="ts"> -import { defineComponent } from "vue"; -import { GameInstall } from "../utils/GameInstall"; -import { InstallProgress } from "../../../src-tauri/bindings/InstallProgress"; -import { invoke } from "@tauri-apps/api"; -import { ReleaseCanal } from "../utils/ReleaseCanal"; -import { Store } from 'tauri-plugin-store-api'; -import { showErrorNotification, showNotification } from "../utils/ui"; -import { appWindow } from "@tauri-apps/api/window"; -const persistentStore = new Store('flight-core-settings.json'); - -export default defineComponent({ - name: "RepairView", - computed: { - lang(): string { - return this.$root!.$i18n.locale; - } - }, - methods: { - async disableAllModsButCore() { - await invoke("disable_all_but_core", { gameInstall: this.$store.state.game_install }) - .then((message) => { - showNotification(this.$t('generic.success'), this.$t('settings.repair.window.disable_all_but_core_success')); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async forceInstallNorthstar() { - // Send notification telling the user to wait for the process to finish - const notification = showNotification( - this.$t('settings.repair.window.reinstall_title'), - this.$t('settings.repair.window.reinstall_text'), - 'info', - 0 - ); - - let install_northstar_result = invoke("install_northstar_wrapper", { gameInstall: this.$store.state.game_install, northstarPackageName: ReleaseCanal.RELEASE }); - - appWindow.listen<InstallProgress>( - 'northstar-install-download-progress', - ({ event, payload }) => { - let typed_payload = payload; - console.log("current_downloaded:", typed_payload.current_downloaded); - console.log("total_size: ", typed_payload.total_size); - console.log("state: ", typed_payload.state); - } - ); - await install_northstar_result - .then((message) => { - // Send notification - showNotification(this.$t('generic.done'), this.$t('settings.repair.window.reinstall_success')); - this.$store.commit('checkNorthstarUpdates'); - }) - .catch((error) => { - showErrorNotification(error); - console.error(error); - }) - .finally(() => { - // Clear old notification - notification.close(); - }); - }, - async cleanUpDownloadFolder() { - await invoke("clean_up_download_folder_wrapper", { gameInstall: this.$store.state.game_install, force: true }).then((message) => { - // Show user notification if task completed. - showNotification(this.$t('generic.done'), this.$t('generic.done')); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async clearFlightCorePersistentStore() { - // Clear store... - await persistentStore.clear(); - // ...and save - await persistentStore.save(); - }, - async disableModsettingsMod() { - await invoke("set_mod_enabled_status", { gameInstall: this.$store.state.game_install, modName: "Mod Settings", isEnabled: false }) - .then((message) => { - showNotification(this.$t('generic.success'), this.$t('settings.repair.window.disable_modsettings_success')); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async killNorthstar() { - await invoke("kill_northstar") - .then((message) => { - // Just a visual indicator that it worked - showNotification('Success'); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - }, - watch: { - // Lang value is propagated to repair view after it's mounted, so we need to watch - // its value, and update window title accordingly. - lang(newv: string) { - appWindow.setTitle(this.$t('settings.repair.window.title')); - } - } -}); -</script> - -<style scoped> -.fc-container { - padding-top: 0px; -} -</style> diff --git a/src-vue/src/views/SettingsView.vue b/src-vue/src/views/SettingsView.vue deleted file mode 100644 index 5ead665b..00000000 --- a/src-vue/src/views/SettingsView.vue +++ /dev/null @@ -1,393 +0,0 @@ -<template> - <el-dialog - v-model="showProfileDialog" - :title="$t('settings.profile.dialog.title')" - width="75%" - > - <el-table :data="availableProfiles" > - <el-table-column prop="name" label="Name" /> - <el-table-column align="right"> - <template #default="scope"> - <el-popconfirm - v-if="scope.row.name != 'R2Northstar'" - :title="$t('settings.profile.dialog.delete_confirm')" - :confirm-button-text="$t('generic.yes')" - :cancel-button-text="$t('generic.no')" - @confirm="deleteProfile(scope.row.name)" - > - <template #reference> - <el-button type="danger"> - {{ $t('settings.profile.dialog.delete') }} - </el-button> - </template> - </el-popconfirm> - <el-button @click="cloneProfileDialog(scope.row.name)"> - {{ $t('settings.profile.dialog.clone') }} - </el-button> - </template> - </el-table-column> - </el-table> - </el-dialog> - - <div class="fc-container"> - <el-scrollbar> - <div class="fc_settings__container"> - <!-- Game folder location --> - <div class="fc_parameter__panel"> - <h3>{{ $t('settings.manage_install') }}</h3> - <el-input - v-model="$store.state.game_install.game_path" - :placeholder="$t('settings.choose_folder')" - @click="updateGamePath" - > - <template #prepend> - <el-button icon="Folder" @click="updateGamePath"/> - </template> - <template #append> - <el-button @click="openGameInstallFolder"> - {{ $t('settings.open_game_folder') }} - </el-button> - </template> - </el-input> - </div> - - <!-- Northstar Active Profile --> - <div class="fc_parameter__panel" v-if="$store.state.developer_mode"> - <h3>{{ $t('settings.profile.active') }}</h3> - <el-dropdown trigger="click" :disabled="!availableProfiles.length"> - <el-button> - {{ activeProfile }} <el-icon class="el-icon--right" v-if="availableProfiles.length"><arrow-down /></el-icon> - </el-button> - <template #dropdown> - <el-dropdown-menu> - <el-dropdown-item v-for="profile in $store.state.available_profiles" @click="switchProfile(profile)">{{ profile }}</el-dropdown-item> - <el-dropdown-item divided @click="showProfileDialog = true">{{ $t('settings.profile.edit') }}</el-dropdown-item> - </el-dropdown-menu> - </template> - </el-dropdown> - </div> - - <!-- Thunderstore mods per page configuration --> - <div class="fc_parameter__panel"> - <h3>{{ $t('settings.nb_ts_mods_per_page') }}</h3> - <h6> - {{ $t('settings.nb_ts_mods_per_page_desc1') }}<br> - {{ $t('settings.nb_ts_mods_per_page_desc2') }} - </h6> - <el-input - v-model="modsPerPage" - type="number" - > - <template #append> - <el-button @click="modsPerPage = 20"> - {{ $t('settings.nb_ts_mods_reset') }} - </el-button> - </template> - </el-input> - </div> - - <div class="fc_parameter__panel"> - <h3>{{ $t('settings.show_deprecated_mods') }}</h3> - <h6> - {{ $t('settings.show_deprecated_mods_desc1') }}<br/> - {{ $t('settings.show_deprecated_mods_desc2') }} - </h6> - <span> - {{ $t('settings.show_deprecated_mods') }} - <el-switch v-model="showDeprecatedMods"></el-switch> - </span> - </div> - - <!-- Interface localization --> - <div class="fc_parameter__panel"> - <h3>{{ $t('settings.language') }}</h3> - <language-selector/> - </div> - - <!-- Repair window --> - <div class="fc_parameter__panel"> - <h3>{{ $t('settings.repair.title') }}</h3> - <el-button type="primary" @click="openRepairWindow"> - {{ $t('settings.repair.open_window') }} - </el-button> - </div> - - <div class="fc_parameter__panel"> - <h3>{{ $t('settings.show_nsfw_mods') }}</h3> - <span> - {{ $t('settings.show_nsfw_mods') }} - <el-switch v-model="showNsfwMods"></el-switch> - </span> - </div> - - <!-- About section --> - <div class="fc_parameter__panel"> - <h3>{{ $t('settings.about') }}</h3> - <div class="fc_northstar__version" @click="activateDeveloperMode"> - {{ $t('settings.flightcore_version') }} {{ flightcoreVersion === '' ? 'Unknown version' : `${flightcoreVersion}` }} - </div> - </div> - - <!-- Testing section --> - <div class="fc_parameter__panel"> - <h3>{{ $t('settings.testing') }}</h3> - <span> - {{ $t('settings.enable_test_channels') }} - <el-switch v-model="enableReleasesSwitch"></el-switch> - </span> - </div> - </div> - </el-scrollbar> - </div> -</template> - -<script lang="ts"> -import { defineComponent } from "vue"; -import { invoke } from "@tauri-apps/api"; -import { ReleaseCanal } from "../utils/ReleaseCanal"; -import { Store } from 'tauri-plugin-store-api'; -import { showErrorNotification, showNotification } from "../utils/ui"; -import LanguageSelector from "../components/LanguageSelector.vue"; -const persistentStore = new Store('flight-core-settings.json'); -import { open } from '@tauri-apps/api/shell'; -import { i18n } from '../main'; -import { ElMessageBox } from 'element-plus' - -export default defineComponent({ - name: "SettingsView", - components: { - LanguageSelector - }, - data() { - return { - developerModeClicks: 0, - showProfileDialog: false, - } - }, - computed: { - showNsfwMods: { - get(): boolean { - return this.$store.state.search.showNsfwMods; - }, - set(value: boolean) { - this.$store.state.search.showNsfwMods = value; - } - }, - showDeprecatedMods: { - get(): boolean { - return this.$store.state.search.showDeprecatedMods; - }, - set(value: boolean) { - this.$store.state.search.showDeprecatedMods = value; - } - }, - flightcoreVersion(): string { - return this.$store.state.flightcore_version; - }, - enableReleasesSwitch: { - get(): boolean { - return this.$store.state.enableReleasesSwitch; - }, - async set(value: boolean): Promise<void> { - this.$store.state.enableReleasesSwitch = value; - persistentStore.set('northstar-releases-switching', { value }); - await persistentStore.save(); // explicit save to disk - - // When disabling switch, we switch release canal to stable release, to avoid users being - // stuck with release candidate after disabling release switching. - if (!value && this.$store.state.northstar_release_canal !== ReleaseCanal.RELEASE) { - this.$store.commit('toggleReleaseCandidate'); - } - } - }, - modsPerPage: { - get(): number { - return this.$store.state.mods_per_page; - }, - async set(value: number) { - this.$store.state.mods_per_page = value; - persistentStore.set('thunderstore-mods-per-page', { value }); - await persistentStore.save(); // explicit save to disk - } - }, - activeProfile(): String { - return this.$store.state.game_install.profile || "None"; - }, - availableProfiles(): Object[] { - let profiles = this.$store.state.available_profiles - - // convert string array to object array so we can fill a table - let data = profiles.reduce( - (a: Object[], v: string) => [...a, {"name": v}], - [] - ); - - return data; - } - }, - methods: { - activateDeveloperMode() { - this.developerModeClicks += 1; - if (this.developerModeClicks >= 6 && !this.$store.state.developer_mode) { - this.$store.commit('toggleDeveloperMode'); - showNotification( - this.$t('settings.dev_mode_enabled_title'), - this.$t('settings.dev_mode_enabled_text'), - 'info' - ); - this.developerModeClicks = 0; - } - }, - async updateGamePath() { - this.$store.commit('updateGamePath'); - }, - async openRepairWindow() { - await invoke("open_repair_window") - .then((message) => { }) - .catch((error) => { - showErrorNotification(error); - }); - }, - async openGameInstallFolder() { - // Verify the game path is actually set - if (!this.$store.state.game_install.game_path) { - showErrorNotification( - i18n.global.tc('notification.game_folder.not_found.text'), - i18n.global.tc('notification.game_folder.not_found.title') - ); - return; - } - - // Opens the folder in default file explorer application - await open(`${this.$store.state.game_install.game_path}`); - }, - async switchProfile(value: string) { - let store = this.$store; - let state = store.state; - - await invoke("validate_profile", { gameInstall: state.game_install, profile: value }) - .then(async (message) => { - if (!message) - { - // Profile is no longer valid, inform the user... - showErrorNotification( - i18n.global.tc('notification.profile.invalid.text'), - i18n.global.tc('notification.profile.invalid.title') - ); - - // ...and refresh - store.commit('fetchProfiles'); - return; - } - - state.game_install.profile = value; - - // Check for Northstar updates - store.commit('checkNorthstarUpdates'); - - // Save change in persistent store - await persistentStore.set('game-install', { value: state.game_install }); - await persistentStore.save(); // explicit save to disk - }) - .catch((error) => { - console.error(error); - showErrorNotification(error); - }); - }, - async cloneProfileDialog(profile: string) { - ElMessageBox.prompt( - i18n.global.tc("settings.profile.dialog.new_profile_name"), - i18n.global.tc("settings.profile.dialog.title"), - { - confirmButtonText: i18n.global.tc("generic.confirm"), - cancelButtonText: i18n.global.tc("generic.cancel"), - } - ).then(async ({ value }) => { - await this.cloneProfile(profile, value); - }).catch(() => { - // Nothing to do here - }) - }, - async cloneProfile(old_profile: string, new_profile: string) { - let store = this.$store; - await invoke("clone_profile", { - gameInstall: store.state.game_install, - oldProfile: old_profile, - newProfile: new_profile - }).then(async (message) => { - store.commit('fetchProfiles'); - showNotification('Success'); - }).catch((error) => { - console.error(error); - showErrorNotification(error); - }); - }, - async deleteProfile(profile: string) { - let store = this.$store; - await invoke("delete_profile", { - gameInstall: store.state.game_install, - profile: profile, - }).then(async (message) => { - if (profile == store.state.game_install.profile) - { - // trying to delete the active profile, lets switch to the default profile - await this.switchProfile("R2Northstar"); - } - store.commit('fetchProfiles'); - showNotification('Success'); - }).catch((error) => { - console.error(error); - showErrorNotification(error); - }); - }, - }, - mounted() { - document.querySelector('input')!.disabled = true; - this.$store.commit('fetchProfiles'); - }, - unmounted() { - if (('' + this.modsPerPage) === '') { - console.warn('Incorrect value for modsPerPage, resetting it to 20.'); - this.modsPerPage = 20; - } - } -}); -</script> - -<style scoped> -.fc_settings__container { - max-width: 1200px; - margin: 0 auto; -} - -h3:first-of-type { - margin-top: 0; - margin-bottom: 1em; - text-transform: uppercase; - font-weight: unset; -} - -.el-input, -.el-select { - width: 50%; -} - -.el-switch { - margin-left: 50px; -} - - -/* Parameter panel styles */ -.fc_parameter__panel { - margin-bottom: 30px; -} - -.fc_parameter__panel h3 { - margin-bottom: 5px; -} - -.fc_parameter__panel h6 { - margin-top: 0; - margin-bottom: 12px; -} -</style> diff --git a/src-vue/src/views/mods/LocalModsView.vue b/src-vue/src/views/mods/LocalModsView.vue deleted file mode 100644 index 3979ca14..00000000 --- a/src-vue/src/views/mods/LocalModsView.vue +++ /dev/null @@ -1,72 +0,0 @@ -<template> - <!-- Message displayed if no mod matched searched words --> - <div v-if="mods.length === 0" class="noModMessage"> - {{ $t('mods.local.no_mods') }} - </div> - - <el-scrollbar v-else> - <el-button class="disableModsBtn" type="primary" @click="disableAllModsButCore"> - {{ $t('settings.repair.window.disable_all_but_core') }} - </el-button> - <local-mod-card v-for="mod of mods" v-bind:key="mod.name" :mod="mod" /> - </el-scrollbar> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import { invoke } from "@tauri-apps/api"; -import { NorthstarMod } from "../../../../src-tauri/bindings/NorthstarMod"; -import { fuzzy_filter } from "../../utils/filter"; -import { showErrorNotification, showNotification } from "../../utils/ui"; -import LocalModCard from "../../components/LocalModCard.vue"; - -export default defineComponent({ - name: 'LocalModsView', - components: { LocalModCard }, - computed: { - installedMods(): NorthstarMod[] { - return this.$store.state.installed_mods; - }, - searchValue(): string { - return this.$store.getters.searchWords; - }, - mods(): NorthstarMod[] { - if (this.searchValue.length === 0) { - return this.installedMods; - } - - return this.installedMods.filter((mod: NorthstarMod) => { - return fuzzy_filter(mod.name, this.searchValue); - }); - } - }, - data() { - return { - global_load_indicator: false, - }; - }, - methods: { - async disableAllModsButCore() { - await invoke("disable_all_but_core", { gameInstall: this.$store.state.game_install }) - .then((message) => { - showNotification(this.$t('generic.success'), this.$t('settings.repair.window.disable_all_but_core_success')); - this.$store.commit('loadInstalledMods'); - }) - .catch((error) => { - showErrorNotification(error); - }); - }, - }, - mounted() { - this.$store.commit('loadInstalledMods'); - } -}) -</script> - -<style scoped> -.disableModsBtn { - margin-bottom: 10px; - top: 10px; - position: sticky; -} -</style> diff --git a/src-vue/src/views/mods/ThunderstoreModsView.vue b/src-vue/src/views/mods/ThunderstoreModsView.vue deleted file mode 100644 index 1ec684a6..00000000 --- a/src-vue/src/views/mods/ThunderstoreModsView.vue +++ /dev/null @@ -1,309 +0,0 @@ -<template>
- <div class="fc-container" style="padding: 0">
- <div v-if="mods.length === 0" class="fc__changelog__container">
- <el-progress :show-text="false" :percentage="50" :indeterminate="true" />
- </div>
-
- <!-- Message displayed if no mod matched searched words -->
- <div v-else-if="filteredMods.length === 0" class="noModMessage">
- {{ $t('mods.online.no_match') }}<br/>
- {{ $t('mods.online.try_another_search') }}
- </div>
-
- <el-scrollbar v-else class="container" ref="scrollbar">
- <div class="card-container">
- <div class="pagination_container" v-if="shouldDisplayPagination">
- <el-pagination
- :currentPage="currentPageIndex + 1"
- layout="prev, pager, next"
- :page-size="modsPerPage"
- :total="modsList.length"
- @update:current-page="onPaginationChange"
- />
- </div>
-
- <!-- Mod cards -->
- <thunderstore-mod-card v-for="mod of currentPageMods" v-bind:key="mod.name" :mod="mod" />
- </div>
-
- <!-- Bottom pagination -->
- <div class="card-container">
- <div class="pagination_container">
- <el-pagination
- class="fc_bottom__pagination"
- v-if="shouldDisplayPagination"
- :currentPage="currentPageIndex + 1"
- layout="prev, pager, next"
- :page-size="modsPerPage"
- :total="modsList.length"
- @update:current-page="onPaginationChange"
- @current-change="scrollTop"
- />
- </div>
- </div>
- </el-scrollbar>
- </div>
-</template>
-
-<script lang="ts">
-import { defineComponent, ref } from 'vue';
-import { ThunderstoreMod } from "../../../../src-tauri/bindings/ThunderstoreMod";
-import ThunderstoreModCard from "../../components/ThunderstoreModCard.vue";
-import { ElScrollbar, ScrollbarInstance } from "element-plus";
-import { SortOptions } from "../../utils/SortOptions.d";
-import { ThunderstoreModVersion } from "../../../../src-tauri/bindings/ThunderstoreModVersion";
-import { fuzzy_filter } from "../../utils/filter";
-import { isThunderstoreModOutdated } from "../../utils/thunderstore/version";
-
-
-export default defineComponent({
- name: "ThunderstoreModsView",
- components: { ThunderstoreModCard },
- async mounted() {
- this.$store.commit('fetchThunderstoreMods');
- },
- computed: {
- showDeprecatedMods(): boolean {
- return this.$store.state.search.showDeprecatedMods;
- },
- showNsfwMods(): boolean {
- return this.$store.state.search.showNsfwMods;
- },
- searchValue(): string {
- return this.$store.getters.searchWords;
- },
- selectedCategories(): Object[] {
- return this.$store.state.search.selectedCategories;
- },
- modSorting(): SortOptions {
- return Object.values(SortOptions)[Object.keys(SortOptions).indexOf(this.$store.state.search.sortValue)];
- },
- mods(): ThunderstoreMod[] {
- return this.$store.state.thunderstoreMods;
- },
- filteredMods(): ThunderstoreMod[] {
- if (this.searchValue.length === 0 && this.selectedCategories.length === 0) {
- return this.mods;
- }
-
- return this.mods.filter((mod: ThunderstoreMod) => {
- // Filter with search words (only if search field isn't empty)
- const inputMatches: boolean = this.searchValue.length === 0
- || (
- fuzzy_filter(mod.name, this.searchValue) ||
- fuzzy_filter(mod.owner, this.searchValue) ||
- mod.versions[0].description.toLowerCase().includes(this.searchValue)
- );
-
- // Filter out deprecated mods
- const showDeprecated = !mod.is_deprecated || this.showDeprecatedMods;
-
- // Filter out NSFW mods
- const showNsfw = !mod.has_nsfw_content || this.showNsfwMods;
-
- // Filter with categories (only if some categories are selected)
- const categoriesMatch: boolean = this.selectedCategories.length === 0
- || mod.categories
- .filter((category: string) => this.selectedCategories.includes(category))
- .length === this.selectedCategories.length;
-
- return inputMatches && categoriesMatch && showDeprecated && showNsfw;
- });
- },
- modsList(): ThunderstoreMod[] {
- // Use filtered mods if user is searching, vanilla list otherwise.
- const mods: ThunderstoreMod[] = this.searchValue.length !== 0 || this.selectedCategories.length !== 0
- ? this.filteredMods
- : this.mods
- .filter(mod => this.showDeprecatedMods || !mod.is_deprecated)
- .filter(mod => this.showNsfwMods || !mod.has_nsfw_content);
-
- // Sort mods regarding user selected algorithm.
- let compare: (a: ThunderstoreMod, b: ThunderstoreMod) => number;
- switch (this.modSorting) {
- case SortOptions.NAME_ASC:
- compare = (a: ThunderstoreMod, b: ThunderstoreMod) => a.name.localeCompare(b.name);
- break;
- case SortOptions.NAME_DESC:
- compare = (a: ThunderstoreMod, b: ThunderstoreMod) => -1 * a.name.localeCompare(b.name);
- break;
- case SortOptions.DATE_ASC:
- compare = (a: ThunderstoreMod, b: ThunderstoreMod) => a.date_updated.localeCompare(b.date_updated);
- break;
- case SortOptions.DATE_DESC:
- compare = (a: ThunderstoreMod, b: ThunderstoreMod) => -1 * a.date_updated.localeCompare(b.date_updated);
- break;
- case SortOptions.MOST_DOWNLOADED:
- compare = (a: ThunderstoreMod, b: ThunderstoreMod) => {
- const aTotal = a.versions.reduce((prev, next) => {
- return { downloads: prev.downloads + next.downloads } as ThunderstoreModVersion;
- }).downloads;
- const bTotal = b.versions.reduce((prev, next) => {
- return { downloads: prev.downloads + next.downloads } as ThunderstoreModVersion;
- }).downloads;
- return -1 * (aTotal - bTotal);
- };
- break;
- case SortOptions.TOP_RATED:
- compare = (a: ThunderstoreMod, b: ThunderstoreMod) => -1 * (a.rating_score - b.rating_score);
- break;
- default:
- throw new Error('Unknown mod sorting.');
- }
-
- // Always display outdated mods first
- // (regardless of actual sort order)
- const sortedMods = mods.sort(compare);
- return sortedMods.sort((a, b) => {
- if (isThunderstoreModOutdated(a)) {
- return -1;
- } else if (isThunderstoreModOutdated(b)) {
- return 1;
- } else {
- return compare(a, b);
- }
- })
- },
- modsPerPage(): number {
- return parseInt(this.$store.state.mods_per_page);
- },
- currentPageMods(): ThunderstoreMod[] {
- // User might want to display all mods on one page.
- const perPageValue = this.modsPerPage != 0 ? this.modsPerPage : this.modsList.length;
-
- const startIndex = this.currentPageIndex * perPageValue;
- const endIndexCandidate = startIndex + perPageValue;
- const endIndex = endIndexCandidate > this.modsList.length ? this.modsList.length : endIndexCandidate;
- return this.modsList.slice(startIndex, endIndex);
- },
- shouldDisplayPagination(): boolean {
- return this.modsPerPage != 0 && this.modsList.length > this.modsPerPage;
- }
- },
- data() {
- return {
- modsBeingInstalled: [] as string[],
- currentPageIndex: 0
- };
- },
- methods: {
- /**
- * This updates current pagination and scrolls view to the top.
- */
- onPaginationChange(index: number) {
- this.currentPageIndex = index - 1;
- },
- scrollTop(index: number) {
- setTimeout(() => {
- (this.$refs.scrollbar as ScrollbarInstance).scrollTo({ top: 0, behavior: 'smooth' });
- }, 100)
- }
- },
- watch: {
- searchValue(_: string, __: string) {
- if (this.currentPageIndex !== 0) {
- this.currentPageIndex = 0;
- }
- },
- selectedCategories(_: string[], __: string[]) {
- if (this.currentPageIndex !== 0) {
- this.currentPageIndex = 0;
- }
- }
- }
-});
-</script>
-
-<style scoped>
-.fc__changelog__container {
- padding: 20px 30px;
-}
-
-.fc-container:deep(.el-scrollbar__view) {
- padding-left: 0;
- padding-right: 0;
-}
-
-.el-timeline-item__timestamp {
- color: white !important;
- user-select: none !important;
-}
-
-.search {
- display: inline-block;
- margin: 0 0 0 10px !important;
-}
-
-.card-container {
- margin: 0 auto;
-}
-
-.pagination_container {
- margin: 5px auto;
- padding: 0 5px;
- max-width: 1000px;
- justify-content: center;
- display: flex;
-}
-
-.el-pagination {
- margin: 0;
-}
-
-.fc_bottom__pagination {
- padding-bottom: 20px !important;
- padding-right: 10px;
-}
-
-/* Card container dynamic size */
-
-.card-container {
- --thunderstore-mod-card-width: 178px;
- --thunderstore-mod-card-margin: 5px;
- --thunderstore-mod-card-columns-count: 1;
-
- width: calc(var(--thunderstore-mod-card-width) * var(--thunderstore-mod-card-columns-count) + var(--thunderstore-mod-card-margin) * 2 * var(--thunderstore-mod-card-columns-count));
-}
-
-@media (min-width: 628px) {
- .card-container {
- --thunderstore-mod-card-columns-count: 2;
- }
-}
-
-@media (min-width: 836px) {
- .card-container {
- --thunderstore-mod-card-columns-count: 3;
- }
-}
-
-@media (min-width: 1006px) {
- .card-container {
- --thunderstore-mod-card-columns-count: 4;
- }
-}
-
-@media (min-width: 1196px) {
- .card-container {
- --thunderstore-mod-card-columns-count: 5;
- }
-}
-
-@media (min-width: 1386px) {
- .card-container {
- --thunderstore-mod-card-columns-count: 6;
- }
-}
-
-@media (min-width: 1576px) {
- .card-container {
- --thunderstore-mod-card-columns-count: 7;
- }
-}
-
-@media (min-width: 1766px) {
- .card-container {
- --thunderstore-mod-card-columns-count: 8;
- }
-}
-</style>
|