mirror of
https://github.com/Grasscutters/Cultivation.git
synced 2026-02-04 09:25:16 +01:00
new release notifications
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cultivation",
|
"name": "cultivation",
|
||||||
"version": "1.0.25",
|
"version": "1.0.26",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^1.0.0-rc.5",
|
"@tauri-apps/api": "^1.0.0-rc.5",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ mod file_helpers;
|
|||||||
mod gamebanana;
|
mod gamebanana;
|
||||||
mod lang;
|
mod lang;
|
||||||
mod proxy;
|
mod proxy;
|
||||||
|
mod release;
|
||||||
mod system_helpers;
|
mod system_helpers;
|
||||||
mod unzip;
|
mod unzip;
|
||||||
mod web;
|
mod web;
|
||||||
@@ -57,7 +58,7 @@ fn main() {
|
|||||||
println!("You running as a non-elevated user. Some stuff will almost definitely not work.");
|
println!("You running as a non-elevated user. Some stuff will almost definitely not work.");
|
||||||
println!("===============================================================================");
|
println!("===============================================================================");
|
||||||
|
|
||||||
reopen_as_admin();
|
//reopen_as_admin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup datadir/cultivation just in case something went funky and it wasn't made
|
// Setup datadir/cultivation just in case something went funky and it wasn't made
|
||||||
@@ -108,6 +109,7 @@ fn main() {
|
|||||||
system_helpers::run_un_elevated,
|
system_helpers::run_un_elevated,
|
||||||
proxy::set_proxy_addr,
|
proxy::set_proxy_addr,
|
||||||
proxy::generate_ca_files,
|
proxy::generate_ca_files,
|
||||||
|
release::get_latest_release,
|
||||||
unzip::unzip,
|
unzip::unzip,
|
||||||
file_helpers::rename,
|
file_helpers::rename,
|
||||||
file_helpers::dir_create,
|
file_helpers::dir_create,
|
||||||
|
|||||||
32
src-tauri/src/release.rs
Normal file
32
src-tauri/src/release.rs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct Release {
|
||||||
|
pub tag_name: String,
|
||||||
|
pub link: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_latest_release() -> Release {
|
||||||
|
let url = "https://api.github.com/repos/Grasscutters/Cultivation/releases/latest";
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let response = client
|
||||||
|
.get(url)
|
||||||
|
.header("User-Agent", "Cultivation")
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let text = response.text().await.unwrap();
|
||||||
|
|
||||||
|
println!("Response: {}", text);
|
||||||
|
|
||||||
|
// Parse "tag_name" from JSON
|
||||||
|
let json: serde_json::Value = serde_json::from_str(&text).unwrap();
|
||||||
|
let tag_name = json["tag_name"].as_str().unwrap();
|
||||||
|
|
||||||
|
// Parse "html_url"
|
||||||
|
let link = json["html_url"].as_str().unwrap();
|
||||||
|
|
||||||
|
Release {
|
||||||
|
tag_name: tag_name.to_string(),
|
||||||
|
link: link.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "Cultivation",
|
"productName": "Cultivation",
|
||||||
"version": "1.0.25"
|
"version": "1.0.26"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ import Downloads from './components/menu/Downloads'
|
|||||||
import NewsSection from './components/news/NewsSection'
|
import NewsSection from './components/news/NewsSection'
|
||||||
import Game from './components/menu/Game'
|
import Game from './components/menu/Game'
|
||||||
import RightBar from './components/RightBar'
|
import RightBar from './components/RightBar'
|
||||||
|
import { ExtrasMenu } from './components/menu/ExtrasMenu'
|
||||||
|
import Notification from './components/common/Notification'
|
||||||
|
|
||||||
import { getConfigOption, setConfigOption } from '../utils/configuration'
|
import { getConfigOption, setConfigOption } from '../utils/configuration'
|
||||||
import { invoke } from '@tauri-apps/api'
|
import { invoke } from '@tauri-apps/api'
|
||||||
|
import { getVersion } from '@tauri-apps/api/app'
|
||||||
import { listen } from '@tauri-apps/api/event'
|
import { listen } from '@tauri-apps/api/event'
|
||||||
import { dataDir } from '@tauri-apps/api/path'
|
import { dataDir } from '@tauri-apps/api/path'
|
||||||
import { appWindow } from '@tauri-apps/api/window'
|
import { appWindow } from '@tauri-apps/api/window'
|
||||||
@@ -24,7 +27,6 @@ import DownloadHandler from '../utils/download'
|
|||||||
import cogBtn from '../resources/icons/cog.svg'
|
import cogBtn from '../resources/icons/cog.svg'
|
||||||
import downBtn from '../resources/icons/download.svg'
|
import downBtn from '../resources/icons/download.svg'
|
||||||
import wrenchBtn from '../resources/icons/wrench.svg'
|
import wrenchBtn from '../resources/icons/wrench.svg'
|
||||||
import { ExtrasMenu } from './components/menu/ExtrasMenu'
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
downloadHandler: DownloadHandler
|
downloadHandler: DownloadHandler
|
||||||
@@ -39,6 +41,7 @@ interface IState {
|
|||||||
extrasOpen: boolean
|
extrasOpen: boolean
|
||||||
migotoSet: boolean
|
migotoSet: boolean
|
||||||
playGame: (exe?: string, proc_name?: string) => void
|
playGame: (exe?: string, proc_name?: string) => void
|
||||||
|
notification: React.ReactElement | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Main extends React.Component<IProps, IState> {
|
export class Main extends React.Component<IProps, IState> {
|
||||||
@@ -55,6 +58,7 @@ export class Main extends React.Component<IProps, IState> {
|
|||||||
playGame: () => {
|
playGame: () => {
|
||||||
alert('Error launching game')
|
alert('Error launching game')
|
||||||
},
|
},
|
||||||
|
notification: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
listen('lang_error', (payload) => {
|
listen('lang_error', (payload) => {
|
||||||
@@ -141,6 +145,35 @@ export class Main extends React.Component<IProps, IState> {
|
|||||||
const updatedConfig = await getConfigOption('patch_rsa')
|
const updatedConfig = await getConfigOption('patch_rsa')
|
||||||
await setConfigOption('patch_rsa', updatedConfig)
|
await setConfigOption('patch_rsa', updatedConfig)
|
||||||
|
|
||||||
|
// Get latest version and compare to this version
|
||||||
|
const latestVersion: {
|
||||||
|
tag_name: string
|
||||||
|
link: string
|
||||||
|
} = await invoke('get_latest_release')
|
||||||
|
const tagName = latestVersion?.tag_name.replace(/[^\d.]/g, '')
|
||||||
|
|
||||||
|
// Check if tagName is different than current version
|
||||||
|
if (tagName && tagName !== (await getVersion())) {
|
||||||
|
// Display notification of new release
|
||||||
|
this.setState({
|
||||||
|
notification: (
|
||||||
|
<>
|
||||||
|
Cultivation{' '}
|
||||||
|
<a href="#" onClick={() => invoke('open_in_browser', { url: latestVersion.link })}>
|
||||||
|
{latestVersion?.tag_name}
|
||||||
|
</a>{' '}
|
||||||
|
is now available!
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState({
|
||||||
|
notification: null,
|
||||||
|
})
|
||||||
|
}, 6000)
|
||||||
|
}
|
||||||
|
|
||||||
// Period check to only show progress bar when downloading files
|
// Period check to only show progress bar when downloading files
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -192,6 +225,8 @@ export class Main extends React.Component<IProps, IState> {
|
|||||||
</div> */}
|
</div> */}
|
||||||
</TopBar>
|
</TopBar>
|
||||||
|
|
||||||
|
<Notification show={!!this.state.notification}>{this.state.notification}</Notification>
|
||||||
|
|
||||||
<RightBar />
|
<RightBar />
|
||||||
|
|
||||||
<NewsSection />
|
<NewsSection />
|
||||||
|
|||||||
24
src/ui/components/common/Notification.css
Normal file
24
src/ui/components/common/Notification.css
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
.Notification {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
/* Default styles, changed when showing notif */
|
||||||
|
top: -100%;
|
||||||
|
right: 10%;
|
||||||
|
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #ffc61e;
|
||||||
|
|
||||||
|
background-color: #fff;
|
||||||
|
color: #000;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NotifShow {
|
||||||
|
top: 10%;
|
||||||
|
}
|
||||||
22
src/ui/components/common/Notification.tsx
Normal file
22
src/ui/components/common/Notification.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import './Notification.css'
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
children: React.ReactNode | null
|
||||||
|
show: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Notification extends React.Component<IProps> {
|
||||||
|
constructor(props: IProps) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className={'Notification ' + (this.props.show ? 'NotifShow' : '')}>
|
||||||
|
<div className="NotificationMessage">{this.props.children}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user