From a22486193ef49113851fab6f277d50f796ecc636 Mon Sep 17 00:00:00 2001
From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>
Date: Tue, 21 Mar 2023 18:28:18 +0100
Subject: Add buttons to download PRs (#203)
* feat: Add button to download Mods PR
Simply opens the browser on the repo download link
* feat: Add button to download Launcher PR
Uses existing function to fetch nightly.link link and opens it in
browser
* refactor: Open Mods PR download link via TS
as opposed to having a link directly
This way it acts the same way as the Launcher PR download button.
Reason behind this change being consistent UI style.
* chore: Revert introduced formatting changes
Those were added by accident, whoops
* fix: Remove introduced unused dependency
* fix: Remove unused dependencies
---
src-vue/src/components/PullRequestsSelector.vue | 10 ++++++++--
src-vue/src/plugins/modules/pull_requests.ts | 21 ++++++++++++++++++++-
2 files changed, 28 insertions(+), 3 deletions(-)
(limited to 'src-vue/src')
diff --git a/src-vue/src/components/PullRequestsSelector.vue b/src-vue/src/components/PullRequestsSelector.vue
index 58a355f4..9ddefc7e 100644
--- a/src-vue/src/components/PullRequestsSelector.vue
+++ b/src-vue/src/components/PullRequestsSelector.vue
@@ -15,6 +15,7 @@
Install
+ Download
{{ pull_request.number }}: {{ pull_request.title }}
@@ -41,6 +42,7 @@
Install
+ Download
{{ pull_request.number }}: {{ pull_request.title }}
@@ -54,8 +56,6 @@
import { defineComponent } from 'vue'
import { PullRequestType } from '../../../src-tauri/bindings/PullRequestType';
import { PullsApiResponseElement } from '../../../src-tauri/bindings/PullsApiResponseElement';
-import { invoke } from "@tauri-apps/api";
-import { ElNotification } from "element-plus";
export default defineComponent({
name: 'PullRequestsSelector',
@@ -80,6 +80,12 @@ export default defineComponent({
async getPullRequests(pull_request_type: PullRequestType) {
this.$store.commit('getPullRequests', pull_request_type);
},
+ async downloadLauncherPR(pull_request: PullsApiResponseElement) {
+ this.$store.commit('downloadLauncherPR', pull_request);
+ },
+ async downloadModsPR(pull_request: PullsApiResponseElement) {
+ this.$store.commit('downloadModsPR', pull_request);
+ },
async installLauncherPR(pull_request: PullsApiResponseElement) {
this.$store.commit('installLauncherPR', pull_request);
},
diff --git a/src-vue/src/plugins/modules/pull_requests.ts b/src-vue/src/plugins/modules/pull_requests.ts
index 573856ad..64c85b77 100644
--- a/src-vue/src/plugins/modules/pull_requests.ts
+++ b/src-vue/src/plugins/modules/pull_requests.ts
@@ -1,5 +1,5 @@
import { ElNotification } from "element-plus";
-import { invoke } from "@tauri-apps/api";
+import { invoke, shell } from "@tauri-apps/api";
import { PullsApiResponseElement } from "../../../../src-tauri/bindings/PullsApiResponseElement";
import { PullRequestType } from '../../../../src-tauri/bindings/PullRequestType';
import { store } from "../store";
@@ -41,6 +41,25 @@ export const pullRequestModule = {
});
});
},
+ async downloadLauncherPR(state: PullRequestStoreState, pull_request: PullsApiResponseElement) {
+ await invoke("get_launcher_download_link", { pullRequest: pull_request })
+ .then((url) => {
+ // Open URL in default HTTPS handler (i.e. default browser)
+ shell.open(url);
+ })
+ .catch((error) => {
+ ElNotification({
+ title: 'Error',
+ message: error,
+ type: 'error',
+ position: 'bottom-right'
+ });
+ });
+ },
+ async downloadModsPR(state: PullRequestStoreState, pull_request: PullsApiResponseElement) {
+ let url = `https://github.com/${pull_request.head.repo.full_name}/archive/refs/heads/${pull_request.head.ref}.zip`
+ shell.open(url);
+ },
async installLauncherPR(state: PullRequestStoreState, pull_request: PullsApiResponseElement) {
// Send notification telling the user to wait for the process to finish
const notification = ElNotification({
--
cgit v1.2.3
From 5e096f84e59eae0ed6b7bb758149c491c87538a6 Mon Sep 17 00:00:00 2001
From: Rémy Raes
Date: Wed, 22 Mar 2023 21:46:12 +0100
Subject: feat: Refresh statistics (#228)
* feat: fetch stats every 5 minutes and ping front with received information
* feat: update front on stats reception
* style: format code
* fix: Add comment
---------
Co-authored-by: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>
---
src-tauri/src/constants.rs | 5 ++++-
src-tauri/src/main.rs | 13 ++++++++++++-
src-vue/src/plugins/store.ts | 5 +++++
3 files changed, 21 insertions(+), 2 deletions(-)
(limited to 'src-vue/src')
diff --git a/src-tauri/src/constants.rs b/src-tauri/src/constants.rs
index 57a10e02..7b13206a 100644
--- a/src-tauri/src/constants.rs
+++ b/src-tauri/src/constants.rs
@@ -1,6 +1,6 @@
// This file stores various global constants values
-
use const_format::concatcp;
+use std::time::Duration;
// FlightCore user agent for web requests
pub const APP_USER_AGENT: &str = concatcp!("FlightCore/", env!("CARGO_PKG_VERSION"));
@@ -34,3 +34,6 @@ pub const PULLS_API_ENDPOINT_LAUNCHER: &str =
"https://api.github.com/repos/R2Northstar/NorthstarLauncher/pulls";
pub const PULLS_API_ENDPOINT_MODS: &str =
"https://api.github.com/repos/R2Northstar/NorthstarMods/pulls";
+
+// Statistics (players and servers counts) refresh delay
+pub const REFRESH_DELAY: Duration = Duration::from_secs(5 * 60);
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index d2f7951d..d5fef9cb 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -10,7 +10,7 @@ use std::{
};
use app::{
- constants::{APP_USER_AGENT, MASTER_SERVER_URL, SERVER_BROWSER_ENDPOINT},
+ constants::{APP_USER_AGENT, MASTER_SERVER_URL, REFRESH_DELAY, SERVER_BROWSER_ENDPOINT},
*,
};
@@ -96,6 +96,17 @@ fn main() {
}
});
+ // Emit updated player and server count to GUI
+ let app_handle = app.app_handle();
+ tauri::async_runtime::spawn(async move {
+ loop {
+ sleep(REFRESH_DELAY).await;
+ app_handle
+ .emit_all("northstar-statistics", get_server_player_count().await)
+ .unwrap();
+ }
+ });
+
Ok(())
})
.manage(Counter(Default::default()))
diff --git a/src-vue/src/plugins/store.ts b/src-vue/src/plugins/store.ts
index 8671d12b..d5b7c5d8 100644
--- a/src-vue/src/plugins/store.ts
+++ b/src-vue/src/plugins/store.ts
@@ -455,6 +455,11 @@ function _initializeListeners(state: any) {
listen("northstar-running-ping", function (evt: TauriEvent) {
state.northstar_is_running = evt.payload as boolean;
});
+
+ listen("northstar-statistics", function (evt: TauriEvent<{Ok: [number, number]}>) {
+ state.player_count = evt.payload.Ok[0];
+ state.server_count = evt.payload.Ok[1];
+ });
}
/**
--
cgit v1.2.3
From 12741098da937ab55d2e1292631217b3a21a3ffa Mon Sep 17 00:00:00 2001
From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>
Date: Mon, 27 Mar 2023 17:58:26 +0200
Subject: fix: Address regression around persistent store (#227)
* fix: Pin tauri-plugin-store package to same commit
Pin npm package to same commit as Rust crate
* fix: Attempt using newest plugin store commit
* fix: Perform explicit save to store on each change
This seems to resolve the issue around no longer writing changes to
store on close as now values are written on each change.
* chore: Pin dependencies to specific commit
Instead of tracking a branch, track a specific commit
---
docs/DEVELOPMENT.md | 1 +
src-tauri/Cargo.lock | 4 ++--
src-tauri/Cargo.toml | 2 +-
src-tauri/src/main.rs | 3 +--
src-vue/package-lock.json | 25 ++++++++++++++++---------
src-vue/package.json | 2 +-
src-vue/src/plugins/store.ts | 3 +++
src-vue/src/views/SettingsView.vue | 6 ++++--
8 files changed, 29 insertions(+), 17 deletions(-)
(limited to 'src-vue/src')
diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md
index 8dbb1cea..0eada12c 100644
--- a/docs/DEVELOPMENT.md
+++ b/docs/DEVELOPMENT.md
@@ -145,6 +145,7 @@ const persistentStore = new Store('flight-core-settings.json');
// Save change in persistent store
await persistentStore.set('northstar-release-canal', { value: "NorthstarReleasecandidate" });
+await persistentStore.save(); // explicit save to disk
// Grab Northstar release canal value from store if exists
var persistent_northstar_release_canal = (await persistentStore.get('northstar-release-canal')) as any;
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index c461ae0a..b407f7bb 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -3969,8 +3969,8 @@ dependencies = [
[[package]]
name = "tauri-plugin-store"
-version = "0.0.0"
-source = "git+https://github.com/tauri-apps/tauri-plugin-store?rev=9bd993aa67766596638bbfd91e79a1bf8f632014#9bd993aa67766596638bbfd91e79a1bf8f632014"
+version = "0.1.0"
+source = "git+https://github.com/tauri-apps/plugins-workspace?rev=5a6abd3203dc94c38f96d0c4bf7ecbef399f8c25#5a6abd3203dc94c38f96d0c4bf7ecbef399f8c25"
dependencies = [
"log",
"serde",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index e8a1d726..8c1415e6 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -43,7 +43,7 @@ sysinfo = "0.26.2"
# HTTP requests
reqwest = { version = "0.11", features = ["blocking"] }
# Persistent store for settings
-tauri-plugin-store = { git = "https://github.com/tauri-apps/tauri-plugin-store", rev = "9bd993aa67766596638bbfd91e79a1bf8f632014" }
+tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "5a6abd3203dc94c38f96d0c4bf7ecbef399f8c25" }
# JSON5 parsing support (allows comments in JSON)
json5 = "0.4.1"
# Async recursion for recursive mod install
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index fb3a8bb2..dfceece7 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -40,7 +40,6 @@ mod thunderstore;
use thunderstore::query_thunderstore_packages_api;
use tauri::{Manager, Runtime};
-use tauri_plugin_store::PluginBuilder;
use tokio::time::sleep;
#[derive(Default)]
@@ -67,7 +66,7 @@ fn main() {
));
tauri::Builder::default()
- .plugin(PluginBuilder::default().build())
+ .plugin(tauri_plugin_store::Builder::default().build())
.setup(|app| {
let app_handle = app.app_handle();
tauri::async_runtime::spawn(async move {
diff --git a/src-vue/package-lock.json b/src-vue/package-lock.json
index bf311673..a652b266 100644
--- a/src-vue/package-lock.json
+++ b/src-vue/package-lock.json
@@ -11,7 +11,7 @@
"@element-plus/icons-vue": "^2.0.9",
"element-plus": "^2.2.17",
"marked": "^4.1.1",
- "tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#dev",
+ "tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#9bd993aa67766596638bbfd91e79a1bf8f632014",
"vue": "^3.2.37",
"vue-router": "^4.1.5",
"vuex": "^4.0.2"
@@ -107,11 +107,11 @@
}
},
"node_modules/@tauri-apps/api": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.2.0.tgz",
- "integrity": "sha512-lsI54KI6HGf7VImuf/T9pnoejfgkNoXveP14pVV7XarrQ46rOejIVJLFqHI9sRReJMGdh2YuCoI3cc/yCWCsrw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.1.0.tgz",
+ "integrity": "sha512-n13pIqdPd3KtaMmmAcrU7BTfdMtIlGNnfZD0dNX8L4p8dgmuNyikm6JAA+yCpl9gqq6I8x5cV2Y0muqdgD0cWw==",
"engines": {
- "node": ">= 14.6.0",
+ "node": ">= 12.22.0",
"npm": ">= 6.6.0",
"yarn": ">= 1.19.1"
},
@@ -1064,13 +1064,20 @@
}
},
"node_modules/tauri-plugin-store-api": {
- "version": "0.0.0",
- "resolved": "git+ssh://git@github.com/tauri-apps/tauri-plugin-store.git#916165e4e4ad9821095584dc02ecd9c295cc9971",
- "license": "MIT or APACHE-2.0",
+ "version": "0.1.0",
+ "resolved": "git+ssh://git@github.com/tauri-apps/tauri-plugin-store.git#9bd993aa67766596638bbfd91e79a1bf8f632014",
+ "integrity": "sha512-X0cDDcEVLY2X8qCLISgAjzuBKDn7bJkj4S7LnXbEPFbPRe+NzhmFGHSAdFCuQuPzQYjmrVg18mZx9NAg4GBHag==",
+ "license": "MIT",
"dependencies": {
- "@tauri-apps/api": "^1.2.0"
+ "@tauri-apps/api": "1.1.0",
+ "tslib": "2.4.0"
}
},
+ "node_modules/tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
+ },
"node_modules/typescript": {
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
diff --git a/src-vue/package.json b/src-vue/package.json
index fbe3fc1a..674ca132 100644
--- a/src-vue/package.json
+++ b/src-vue/package.json
@@ -12,7 +12,7 @@
"@element-plus/icons-vue": "^2.0.9",
"element-plus": "^2.2.17",
"marked": "^4.1.1",
- "tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#dev",
+ "tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#9bd993aa67766596638bbfd91e79a1bf8f632014",
"vue": "^3.2.37",
"vue-router": "^4.1.5",
"vuex": "^4.0.2"
diff --git a/src-vue/src/plugins/store.ts b/src-vue/src/plugins/store.ts
index d5b7c5d8..caa46bee 100644
--- a/src-vue/src/plugins/store.ts
+++ b/src-vue/src/plugins/store.ts
@@ -143,6 +143,7 @@ export const store = createStore({
// Save change in persistent store
await persistentStore.set('game-install', { value: game_install });
+ await persistentStore.save(); // explicit save to disk
// Check for Northstar install
store.commit('checkNorthstarUpdates');
@@ -307,6 +308,7 @@ export const store = createStore({
// Save change in persistent store
await persistentStore.set('northstar-release-canal', { value: state.northstar_release_canal });
+ await persistentStore.save(); // explicit save to disk
// Update current state so that update check etc can be performed
store.commit("checkNorthstarUpdates");
@@ -407,6 +409,7 @@ async function _initializeApp(state: any) {
// Save change in persistent store
await persistentStore.set('game-install', { value: typedResult });
+ await persistentStore.save(); // explicit save to disk
// Update UI store
state.game_path = typedResult.game_path;
diff --git a/src-vue/src/views/SettingsView.vue b/src-vue/src/views/SettingsView.vue
index c93d69ff..4e816740 100644
--- a/src-vue/src/views/SettingsView.vue
+++ b/src-vue/src/views/SettingsView.vue
@@ -78,9 +78,10 @@ export default defineComponent({
get(): boolean {
return this.$store.state.enableReleasesSwitch;
},
- set(value: boolean): void {
+ async set(value: boolean): Promise {
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.
@@ -93,9 +94,10 @@ export default defineComponent({
get(): number {
return this.$store.state.mods_per_page;
},
- set(value: number) {
+ 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
}
}
},
--
cgit v1.2.3
From 4cdfc0ea04844681de078d26f44321cb3c3b05c5 Mon Sep 17 00:00:00 2001
From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>
Date: Mon, 27 Mar 2023 18:10:46 +0200
Subject: feat: Generate FlightCore release notes (#188)
* feat: Generate FlightCore release notes
* fix: Remove leftover comment
* fix: Add missing semantic commit type
* fix: Re-add newlines accidentally removed in merge
* refactor: Remove contributors section
Will re-add a proper implementation in a later PR.
* fix: Revert accidentally modified line
* docs: Update comments
* fix: Use correct user-agent
* fix: Put unknown commits into "Other" section
Previously they were just dropped
* refactor: Move constant string array to right file
* fix: Remove debug prints
* refactor: Move lib import to start of file
* refactor: Use wrapper type
kinda needed by selector in frontend.
Allows for still passing full object to backend for future extensability
* fix: Generate missing wrapper TS interface
* fix: Add title and message to notification
* refactor: Move constant to consts file
* fix: Fix formatting
* fix: Remove unnecessary property declaration
---
src-tauri/bindings/Tag.ts | 3 +
src-tauri/bindings/TagWrapper.ts | 4 +
src-tauri/src/constants.rs | 8 ++
src-tauri/src/github/mod.rs | 176 ++++++++++++++++++++++++++++++++++++
src-tauri/src/main.rs | 3 +
src-vue/src/views/DeveloperView.vue | 95 +++++++++++++++++++
6 files changed, 289 insertions(+)
create mode 100644 src-tauri/bindings/Tag.ts
create mode 100644 src-tauri/bindings/TagWrapper.ts
(limited to 'src-vue/src')
diff --git a/src-tauri/bindings/Tag.ts b/src-tauri/bindings/Tag.ts
new file mode 100644
index 00000000..adbbff33
--- /dev/null
+++ b/src-tauri/bindings/Tag.ts
@@ -0,0 +1,3 @@
+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+
+export interface Tag { name: string, }
\ No newline at end of file
diff --git a/src-tauri/bindings/TagWrapper.ts b/src-tauri/bindings/TagWrapper.ts
new file mode 100644
index 00000000..f9f56a51
--- /dev/null
+++ b/src-tauri/bindings/TagWrapper.ts
@@ -0,0 +1,4 @@
+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+import type { Tag } from "./Tag";
+
+export interface TagWrapper { label: string, value: Tag, }
\ No newline at end of file
diff --git a/src-tauri/src/constants.rs b/src-tauri/src/constants.rs
index 7b13206a..0f4e9ab4 100644
--- a/src-tauri/src/constants.rs
+++ b/src-tauri/src/constants.rs
@@ -29,6 +29,11 @@ pub const BLACKLISTED_MODS: [&str; 3] = [
// Titanfall2 game IDs on Origin/EA-App
pub const TITANFALL2_ORIGIN_IDS: [&str; 2] = ["Origin.OFR.50.0001452", "Origin.OFR.50.0001456"];
+// Order in which the sections for release notes should be displayed
+pub const SECTION_ORDER: [&str; 9] = [
+ "feat", "fix", "docs", "style", "refactor", "build", "test", "chore", "other",
+];
+
// GitHub API endpoints for launcher/mods PRs
pub const PULLS_API_ENDPOINT_LAUNCHER: &str =
"https://api.github.com/repos/R2Northstar/NorthstarLauncher/pulls";
@@ -37,3 +42,6 @@ pub const PULLS_API_ENDPOINT_MODS: &str =
// Statistics (players and servers counts) refresh delay
pub const REFRESH_DELAY: Duration = Duration::from_secs(5 * 60);
+
+// Flightcore repo name and org name on GitHub
+pub const FLIGHTCORE_REPO_NAME: &str = "R2NorthstarTools/FlightCore";
diff --git a/src-tauri/src/github/mod.rs b/src-tauri/src/github/mod.rs
index 942f0db2..87ea629c 100644
--- a/src-tauri/src/github/mod.rs
+++ b/src-tauri/src/github/mod.rs
@@ -1,2 +1,178 @@
pub mod pull_requests;
pub mod release_notes;
+
+use app::constants::{APP_USER_AGENT, FLIGHTCORE_REPO_NAME, SECTION_ORDER};
+use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
+use ts_rs::TS;
+
+#[derive(Serialize, Deserialize, Debug, Clone, TS)]
+#[ts(export)]
+pub struct Tag {
+ name: String,
+}
+
+/// Wrapper type needed for frontend
+#[derive(Serialize, Deserialize, Debug, Clone, TS)]
+#[ts(export)]
+pub struct TagWrapper {
+ label: String,
+ value: Tag,
+}
+
+#[derive(Debug, Deserialize)]
+struct CommitInfo {
+ sha: String,
+ commit: Commit,
+}
+
+#[derive(Debug, Deserialize)]
+struct Commit {
+ message: String,
+}
+
+#[derive(Debug, Deserialize)]
+struct Comparison {
+ commits: Vec,
+}
+
+/// Get a list of tags on the FlightCore repo
+#[tauri::command]
+pub fn get_list_of_tags() -> Result, String> {
+ // Set the repository name.
+
+ // Create a `reqwest` client with a user agent.
+ let client = reqwest::blocking::Client::builder()
+ .user_agent(APP_USER_AGENT)
+ .build()
+ .unwrap();
+
+ // Fetch the list of tags for the repository as a `Vec`.
+ let tags_url = format!("https://api.github.com/repos/{}/tags", FLIGHTCORE_REPO_NAME);
+ let tags: Vec = client.get(&tags_url).send().unwrap().json().unwrap();
+
+ // Map each `Tag` element to a `TagWrapper` element with the desired label and `Tag` value.
+ let tag_wrappers: Vec = tags
+ .into_iter()
+ .map(|tag| TagWrapper {
+ label: tag.name.clone(),
+ value: tag,
+ })
+ .collect();
+
+ Ok(tag_wrappers)
+}
+
+/// Use GitHub API to compare two tags of the same repo against each other and get the resulting changes
+#[tauri::command]
+pub fn compare_tags(first_tag: Tag, second_tag: Tag) -> Result {
+ // Fetch the list of commits between the two tags.
+
+ // Create a `reqwest` client with a user agent.
+ let client = reqwest::blocking::Client::builder()
+ .user_agent(APP_USER_AGENT)
+ .build()
+ .unwrap();
+
+ let repo = "R2NorthstarTools/FlightCore";
+
+ let mut full_patch_notes = "".to_string();
+
+ let mut patch_notes: Vec = [].to_vec();
+ println!("{}", repo);
+ // let repo = "R2Northstar/NorthstarLauncher";
+ let comparison_url = format!(
+ "https://api.github.com/repos/{}/compare/{}...{}",
+ repo, first_tag.name, second_tag.name
+ );
+
+ let comparison: Comparison = client.get(&comparison_url).send().unwrap().json().unwrap();
+ let commits = comparison.commits;
+
+ // Display the list of commits.
+ println!(
+ "Commits between {} and {}:",
+ first_tag.name, second_tag.name
+ );
+
+ // Iterate over all commits in the diff
+ for commit in commits {
+ println!(
+ " * {} : {}",
+ commit.sha,
+ commit.commit.message.split('\n').next().unwrap()
+ );
+ patch_notes.push(format!(
+ "{}",
+ commit.commit.message.split('\n').next().unwrap()
+ ));
+ }
+
+ full_patch_notes += &generate_flightcore_release_notes(patch_notes);
+
+ Ok(full_patch_notes.to_string())
+}
+
+/// Generate release notes in the format used for FlightCore
+fn generate_flightcore_release_notes(commits: Vec) -> String {
+ let grouped_commits = group_commits_by_type(commits);
+ let mut release_notes = String::new();
+
+ // Go over commit types and generate notes
+ for commit_type in SECTION_ORDER {
+ if let Some(commit_list) = grouped_commits.get(commit_type) {
+ if !commit_list.is_empty() {
+ let section_title = match commit_type {
+ "feat" => "**Features:**",
+ "fix" => "**Bug Fixes:**",
+ "docs" => "**Documentation:**",
+ "style" => "**Styles:**",
+ "refactor" => "**Code Refactoring:**",
+ "build" => "**Build:**",
+ "test" => "**Tests:**",
+ "chore" => "**Chores:**",
+ _ => "**Other:**",
+ };
+
+ release_notes.push_str(&format!("{}\n", section_title));
+
+ for commit_message in commit_list {
+ release_notes.push_str(&format!("- {}\n", commit_message));
+ }
+
+ release_notes.push_str("\n");
+ }
+ }
+ }
+
+ release_notes
+}
+
+/// Group semantic commit messages by type
+/// Commmit messages that are not formatted accordingly are marked as "other"
+fn group_commits_by_type(commits: Vec) -> HashMap> {
+ let mut grouped_commits: HashMap> = HashMap::new();
+ let mut other_commits: Vec = vec![];
+
+ for commit in commits {
+ let commit_parts: Vec<&str> = commit.splitn(2, ":").collect();
+ if commit_parts.len() == 2 {
+ let commit_type = commit_parts[0].to_lowercase();
+ let commit_description = commit_parts[1].trim().to_string();
+
+ // Check if known commit type
+ if SECTION_ORDER.contains(&commit_type.as_str()) {
+ let commit_list = grouped_commits.entry(commit_type.to_string()).or_default();
+ commit_list.push(commit_description);
+ } else {
+ // otherwise add to list of "other"
+ other_commits.push(commit.to_string());
+ }
+ } else {
+ other_commits.push(commit.to_string());
+ }
+ }
+ grouped_commits.insert("other".to_string(), other_commits);
+
+ grouped_commits
+}
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index dfceece7..f4712cd4 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -21,6 +21,7 @@ use github::pull_requests::{
use github::release_notes::{
check_is_flightcore_outdated, get_newest_flightcore_version, get_northstar_release_notes,
};
+use github::{compare_tags, get_list_of_tags};
mod repair_and_verify;
use repair_and_verify::{
@@ -137,6 +138,8 @@ fn main() {
delete_thunderstore_mod,
open_repair_window,
query_thunderstore_packages_api,
+ get_list_of_tags,
+ compare_tags,
get_pull_requests_wrapper,
apply_launcher_pr,
apply_mods_pr,
diff --git a/src-vue/src/views/DeveloperView.vue b/src-vue/src/views/DeveloperView.vue
index 52117b8d..bca473fb 100644
--- a/src-vue/src/views/DeveloperView.vue
+++ b/src-vue/src/views/DeveloperView.vue
@@ -5,6 +5,38 @@
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!
+
+ Get tags
+
+
+
+
+
+
+
+
+
+
+ Compare Tags
+
+
+
+
Basic:
@@ -53,6 +85,7 @@ import { defineComponent } from "vue";
import { invoke } from "@tauri-apps/api";
import { ElNotification } from "element-plus";
import { GameInstall } from "../utils/GameInstall";
+import { TagWrapper } from "../../../src-tauri/bindings/TagWrapper";
import PullRequestsSelector from "../components/PullRequestsSelector.vue";
export default defineComponent({
@@ -63,8 +96,30 @@ export default defineComponent({
data() {
return {
mod_to_install_field_string : "",
+ release_notes_text : "",
+ first_tag: { label: '', value: {name: ''} },
+ second_tag: { label: '', value: {name: ''} },
+ ns_release_tags: [] as TagWrapper[],
}
},
+ 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');
@@ -152,6 +207,46 @@ export default defineComponent({
});
});
},
+ async getTags() {
+ await invoke("get_list_of_tags")
+ .then((message) => {
+ this.ns_release_tags = message;
+ ElNotification({
+ title: "Done",
+ message: "Fetched tags",
+ type: 'success',
+ position: 'bottom-right'
+ });
+ })
+ .catch((error) => {
+ ElNotification({
+ title: 'Error',
+ message: error,
+ type: 'error',
+ position: 'bottom-right'
+ });
+ });
+ },
+ async compareTags() {
+ await invoke("compare_tags", {firstTag: this.firstTag.value, secondTag: this.secondTag.value})
+ .then((message) => {
+ this.release_notes_text = message;
+ ElNotification({
+ title: "Done",
+ message: "Generated release notes",
+ type: 'success',
+ position: 'bottom-right'
+ });
+ })
+ .catch((error) => {
+ ElNotification({
+ title: 'Error',
+ message: error,
+ type: 'error',
+ position: 'bottom-right'
+ });
+ });
+ },
}
});
--
cgit v1.2.3
From 428c300e9f42f8b9232f780d387292c1a94fcd23 Mon Sep 17 00:00:00 2001
From: Rémy Raes
Date: Wed, 29 Mar 2023 00:45:16 +0200
Subject: feat: i18n (#182)
* build: add vue-i18n dependency
* feat: add i18n plugin to vue project
* feat: use translations in play button
* feat: translate play view
* feat: translate menu items
* feat: translate local mods view
* feat: translate online mods view
* feat: translate mods menu
* feat: translate thunderstore mod card component
* fix: remove useless "this" keyword
* feat: translate settings view
* fix: remove leftover test invocation
* feat: add language selector component
* feat: using language selector updates interface's language
* feat: save language in persistent store on selector change
* feat: initialize lang on app launch
* refactor: move i18n code into App.mounted callback
* feat: update interface language on app launch
* feat: adjust language selection on language selector load
* fix: this.$root can't be null
* feat: translate store notifications
* fix: add missing parameter to english translation
* feat: translate "by" author keyword
* feat: translate repair window
* feat: translate repair window title
* docs: add some documentation regarding localization
* docs: explain how to add a new language
* feat: translate Northstar release canal selector elements
* docs: describe how to inject variable into translations
* feat: translate "info" word
* feat: translate popconfirm buttons
* fix: remove "this" keyword
* fix: save store when updating interface language
---
docs/DEVELOPMENT.md | 60 +
src-vue/package-lock.json | 1544 ++++++++++++++---------
src-vue/package.json | 1 +
src-vue/src/App.vue | 25 +-
src-vue/src/components/LanguageSelector.vue | 47 +
src-vue/src/components/ModsMenu.vue | 14 +-
src-vue/src/components/PlayButton.vue | 16 +-
src-vue/src/components/ThunderstoreModCard.vue | 34 +-
src-vue/src/i18n/lang/en.ts | 156 +++
src-vue/src/i18n/lang/fr.ts | 156 +++
src-vue/src/main.ts | 12 +
src-vue/src/plugins/store.ts | 26 +-
src-vue/src/utils/SortOptions.d.ts | 12 +-
src-vue/src/views/PlayView.vue | 14 +-
src-vue/src/views/RepairView.vue | 27 +-
src-vue/src/views/SettingsView.vue | 47 +-
src-vue/src/views/mods/LocalModsView.vue | 18 +-
src-vue/src/views/mods/ThunderstoreModsView.vue | 4 +-
18 files changed, 1535 insertions(+), 678 deletions(-)
create mode 100644 src-vue/src/components/LanguageSelector.vue
create mode 100644 src-vue/src/i18n/lang/en.ts
create mode 100644 src-vue/src/i18n/lang/fr.ts
(limited to 'src-vue/src')
diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md
index 0eada12c..02832722 100644
--- a/docs/DEVELOPMENT.md
+++ b/docs/DEVELOPMENT.md
@@ -179,6 +179,66 @@ struct User {
then simply run `cargo test`. The generated bindings are placed in `src-tauri/bindings/`. Make sure to add and commit them as well!
+### Internationalization
+
+For FlightCore to be used by the largest number, its interface is translated in several languages; users can choose used language through FlightCore settings.
+
+Localization files are located in `src-vue/src/i18n/lang`.
+
+To add a new language, you have to create associated file, *e.g. `src-vue/src/i18n/lang/de.ts`*, and import it in the i18n application object in `main.ts`:
+```javascript
+import de from "./i18n/lang/de";
+
+export const i18n = createI18n({
+ locale: 'en',
+ fallbackLocale: 'en',
+ messages: {
+ en, fr, de
+ }
+});
+```
+
+There are different ways to use translations in views; in HTML template, invoke the `$t` method with translation key:
+
+```html
+
-
- This window contains various functionality to repair common issues with Northstar and FlightCore.
+
+ {{ $t('settings.repair.window.warning') }}
-
Repair
+
{{ $t('settings.repair.title') }}
Northstar
- Disable all but core mods
+ {{ $t('settings.repair.window.disable_all_but_core') }}
- Force reinstall Northstar
+ {{ $t('settings.repair.window.force_reinstall_ns') }}
FlightCore
- Force delete temp download folder
+ {{ $t('settings.repair.window.force_delete_temp_dl') }}
- Delete FlightCore persistent store
+ {{ $t('settings.repair.window.delete_persistent_store') }}
@@ -37,10 +37,16 @@ import { GameInstall } from "../utils/GameInstall";
import { invoke } from "@tauri-apps/api";
import { ReleaseCanal } from "../utils/ReleaseCanal";
import { Store } from 'tauri-plugin-store-api';
+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() {
let game_install = {
@@ -135,6 +141,13 @@ export default defineComponent({
// ...and save
await persistentStore.save();
},
+ },
+ 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') );
+ }
}
});
diff --git a/src-vue/src/views/SettingsView.vue b/src-vue/src/views/SettingsView.vue
index 4e816740..9a92865d 100644
--- a/src-vue/src/views/SettingsView.vue
+++ b/src-vue/src/views/SettingsView.vue
@@ -3,11 +3,11 @@
-
Manage installation
+
{{ $t('settings.manage_install') }}
@@ -17,37 +17,46 @@
-
Number of Thunderstore mods per page
+
{{ $t('settings.nb_ts_mods_per_page') }}
- This has an impact on display performances when browsing Thunderstore mods.
- Set this value to 0 to disable pagination.
+ {{ $t('settings.nb_ts_mods_per_page_desc1') }}
+ {{ $t('settings.nb_ts_mods_per_page_desc2') }}