aboutsummaryrefslogtreecommitdiff
path: root/src-vue/src/views
diff options
context:
space:
mode:
Diffstat (limited to 'src-vue/src/views')
-rw-r--r--src-vue/src/views/ChangelogView.vue82
-rw-r--r--src-vue/src/views/DeveloperView.vue369
-rw-r--r--src-vue/src/views/ModsView.vue54
-rw-r--r--src-vue/src/views/PlayView.vue124
-rw-r--r--src-vue/src/views/RepairView.vue153
-rw-r--r--src-vue/src/views/SettingsView.vue393
-rw-r--r--src-vue/src/views/mods/LocalModsView.vue72
-rw-r--r--src-vue/src/views/mods/ThunderstoreModsView.vue309
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>