Commit 44367f7b authored by Сергей Штурнев's avatar Сергей Штурнев

Merge branch 'develop' into 'master'

v1.0.3

See merge request !3
parents 14ceacdc dc1cb497
Pipeline #122673435 failed with stages
in 1 minute and 4 seconds
......@@ -8,7 +8,7 @@
It's simple, I love vr-photo and vr-video, and I even have a camera for this, and I also like linux... it's all great, but in order to watch my (or your) cool vr’s I had to switch to windows, which is at least not convenient! And the search for suitable software did not materialize. Well, enough to endure it - I decided, and started developing this application. So **sht-vr-player** appeared, and I hope that it will be useful to you as well as to me.
### Where can I download?
At this link: [sht-vr-player_1.0.1_amd64.deb](https://my.pcloud.com/publink/show?code=XZlmn4kZh2DsnkU4ni8GqYpLEH9eTynjzLN7)
Here https://sht-vr-player.cf/ always fresh version
## What can?
* View directory, convenient preview of media files.
......@@ -38,9 +38,7 @@ At this link: [sht-vr-player_1.0.1_amd64.deb](https://my.pcloud.com/publink/show
* And if you are like a programmer, then vr-player is open to your code. It is created under the open MIT license, and you can safely make your changes (I'm waiting for your pull-requests ) .
## Are you in touch?
Of course, you can always contact me at this email: **[email protected]**
\ No newline at end of file
Of course, you can always contact me at this email: **[email protected]**
This diff is collapsed.
{
"version": "1.0.2",
"version": "1.0.3",
"name": "sht-vr-player",
"author": "Shturnev Sergey <[email protected]>",
"license": "MIT",
......@@ -17,7 +17,7 @@
],
"scripts": {
"serve": "vue-cli-service serve",
"buildp": "vue-cli-service build",
"build": "vue-cli-service build",
"test": "jest",
"electron:build": "vue-cli-service electron:build --config electron-builder.json",
"electron:serve": "vue-cli-service electron:serve",
......@@ -42,6 +42,7 @@
"@vue/cli-plugin-unit-jest": "^3.11.0",
"@vue/cli-service": "^3.11.0",
"@vue/test-utils": "1.0.0-beta.29",
"axios": "^0.19.2",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "^25.0.0",
"babel-plugin-transform-imports": "1.5.0",
......@@ -51,8 +52,10 @@
"electron": "^7.1.9",
"electron-builder": "^22.2.0",
"express": "^4.17.1",
"form-data": "^3.0.0",
"get-folder-size": "^2.0.1",
"gm": "^1.23.1",
"jest": "^25.1.0",
"lodash": "^4.17.15",
"rimraf": "latest",
"sass": "^1.18.0",
......
/**
* Default settings for project
*
*
*/
export default {
version: "1.0.3",
checkUpdates: true,
albumId: "08cbdbd1238d321", //It is the id of folder where we storing binaries for install
downloadLink: "https://upfiler.sht-server.cf/#/download/?t=file&h=",
}
......@@ -36,7 +36,6 @@ protocol.registerSchemesAsPrivileged([{scheme: 'app', privileges: { secure: true
function createWindow () {
// Create the browser window.
let opt = { width: 800, height: 600, webPreferences: {
nodeIntegration: true
......
import da from "quasar/lang/da";
const fs = require("fs");
import baseConfig from "../../project.config";
const homePath = require('os').homedir() + '/.sht-vr-player';
import _ from 'lodash';
class ConfigModel {
constructor() {
if(!homePath){throw new Error("No home path specified")}
this.configPath = homePath + "/config.json";
}
/**
* Save (load) settings into file
*
* @param settingsObj - data (object) for save
*/
loadSettings(settingsObj){
if(!settingsObj){ return true; }
if (!this.configPath){throw new Error("Could not store the settings. Config path did not specified")}
//write to file
let res = fs.writeFileSync(this.configPath, JSON.stringify(settingsObj));
return res === undefined
}
/**
* Get settings from file, if not exists then global
*/
getSettings(){
if(!fs.existsSync(this.configPath)){
this.loadSettings(baseConfig, );
return baseConfig;
}
let data = fs.readFileSync(this.configPath, 'utf8');
data = JSON.parse(data);
//update old settings (after installing updated version)
if(data.version !== baseConfig.version){
data.version = baseConfig.version;
data = _.merge(data, baseConfig);
this.loadSettings(data);
}
return data;
}
}
export default ConfigModel;
......@@ -5,6 +5,8 @@ import {dialog, ipcMain} from 'electron'
import {Helper} from './Helper'
import {Media} from "./Media";
import path from 'path'
import ConfigModel from "./ConfigModel";
import Updater from "./Updater";
const homedir = require('os').homedir() + '/.sht-vr-player';
const clr = require('cli-color');
......@@ -17,7 +19,9 @@ class MainModelClass {
constructor(win) {
this.win = win;
this.serverUrl = undefined;
this.homedir = homedir;
this.static_dir = homedir + '/static';
this.config = new ConfigModel();
}
......@@ -48,6 +52,29 @@ class MainModelClass {
})
});
ipcMain.on('delete-cache', (event, items) => this.deleteCache(event, items));
ipcMain.on('get-config', (event) => event.reply('config-data', this.config.getSettings()) );
ipcMain.on('save-config', (event, data) => this.config.loadSettings(data) );
/*-----------------------------------
Check for update
-----------------------------------*/
ipcMain.on('check-for-update', (event) => {
let configData = this.config.getSettings();
if(configData.checkUpdates){
Updater.check(configData).then(res => {
if(!res){return}
event.reply('need-to-update', res);
}).catch(err => {
console.log(clr.red(err));
event.reply('show-error', err);
})
}
});
}
......@@ -168,7 +195,6 @@ class MainModelClass {
return true
}
deleteCache(event, items = []) {
//if no items loaded delete static dir with all inside
if(!items.length){
......@@ -187,7 +213,7 @@ class MainModelClass {
console.log(`Cache was deleted`);
return;
}
//else. read and delete thump and links dir
removeFilesHelper(path.join(this.static_dir, 'small'), items.map(i => i['thumpName']));
removeFilesHelper(path.join(this.static_dir, 'big'), items.map(i => i['bigName']));
......@@ -222,4 +248,4 @@ function removeFilesHelper(dirPath, names){
}
export {MainModelClass, removeFilesHelper}
\ No newline at end of file
export {MainModelClass, removeFilesHelper}
const request = require('request');
const querystring = require('querystring');
const api_url = "https://upfiler.sht-server.cf/api/";
class Updater {
/**
* Check for updates
*
* @param configData- {version, checkUpdates, albumId}
* @return Promise (false or objectData)
*/
static async check(configData){
if(!configData.checkUpdates){return false;}
let forSend = {
"action": "file_get_last_in_album",
"album_hash": configData.albumId
};
let resData = await new Promise((resolve, reject) => {
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: api_url,
body: querystring.stringify(forSend)
}, function(error, response, body){
if(error){ reject(error); return; }
let res = JSON.parse(body);
if(res.error_desc){ reject(res.error_desc); return; }
resolve(res.data);
});
});
let serverVersion = resData.filename_orig.split("_")[1];
if(configData.version === serverVersion){return false;}
return resData;
}
}
export default Updater;
......@@ -40,6 +40,7 @@ import {
QToolbarTitle,
QTooltip,
Quasar,
QToggle
} from 'quasar'
Vue.use(Quasar, {
......@@ -76,6 +77,7 @@ Vue.use(Quasar, {
QSpace,
QSeparator,
QSlider,
QToggle
},
directives: {
ClosePopup,
......@@ -85,4 +87,4 @@ Vue.use(Quasar, {
Dialog,
},
animations: 'all'
})
\ No newline at end of file
})
......@@ -2,7 +2,6 @@ import Vue from 'vue'
import Router from 'vue-router'
import DefaultLayout from './layouts/Default.vue'
import Home from './views/Home.vue'
import About from './views/About.vue'
Vue.use(Router)
......@@ -17,11 +16,6 @@ export default new Router({
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
}
]
}
]
......
......@@ -2,19 +2,23 @@ import Vue from 'vue'
import Vuex from 'vuex'
import {shell} from 'electron'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
},
state: {
MS: null,
can_select: false,
can_open_dir: true,
static_files_url: "",
total_items:0,
total_items: 0,
open_settings: false,
},
getters: {
},
mutations: {
set(state, data) {
......@@ -24,7 +28,7 @@ export default new Vuex.Store({
actions: {
openExternalLink(context, link){
shell.openExternal(link);
},
}
}
})
<template>
<q-page padding>
<p>This is an about page</p>
</q-page>
</template>
<script>
export default {
name: 'PageAbout'
}
</script>
......@@ -116,28 +116,51 @@
</q-card-section>
<q-card-section>
<div class="row items-center">
<div class="">Clear data cache - <b>{{cacheSize}} MB</b></div>
<q-list separator>
<q-item clickable @click="deleteCache()">
<q-item-section>Clear data cache</q-item-section>
<q-item-section side>
<b>{{cacheSize}} MB</b>
</q-item-section>
</q-item>
<q-item v-if="configData" clickable @click="set_checkUpdates">
<q-item-section>Check for updates</q-item-section>
<q-item-section side>
<q-toggle color="secondary" @input="set_checkUpdates" :value="configData.checkUpdates"/>
</q-item-section>
</q-item>
</q-list>
<!--<div class="row items-center">
<div>Clear data cache - <b>{{cacheSize}} MB</b></div>
<q-space/>
<q-btn :loading="deleteCacheloading" icon="delete" round size="xs" @click="deleteCache()"/>
</div>
<div class="row items-center">
<div>Check for updates</div>
<q-space/>
<q-btn :loading="deleteCacheloading" icon="delete" round size="xs" @click="deleteCache()"/>
</div>-->
<q-separator class="q-my-md"/>
<div class="text-center">
<p>Please donate to the project! This will help me continue to work on it and add improvements! Thanks!</p>
<q-btn @click="openExternalLink('https://www.liqpay.ua/en/checkout/shtvrplayer')">
<q-icon color="red" name="favorite"/>
Be a sponsor!
Became a sponsor!
</q-btn>
</div>
<br>
<div class="text-center">
Created by <a class="text-secondary" href=""
@click.prevent="openExternalLink('https://www.facebook.com/sergey.shturnev')">Shturnev
@click.prevent="openExternalLink('https://www.facebook.com/sergey.shturnev')">Shturnev
Sergey</a>
</div>
......@@ -152,7 +175,7 @@
<script>
import {Pano} from 'vuejs-vr'
import {mapActions, mapState} from 'vuex'
import {ipcRenderer} from 'electron'
import {ipcRenderer,} from 'electron'
import _ from 'lodash'
......@@ -173,10 +196,16 @@
showingItemDialog: false,
showingItem: {},
cacheSize: 0,
deleteCacheloading: false
deleteCacheloading: false,
configData: {}
}
},
computed: {
...mapState([
'static_files_url',
'can_open_dir',
'total_items',
]),
total_selected() {
return this.items.filter(item => item.selected).length
},
......@@ -197,7 +226,9 @@
this.$store.commit("set", ['open_settings', val])
},
},
...mapState(['static_files_url', 'can_open_dir', 'total_items'])
ttest() {
return this.configData.checkUpdates
}
},
watch: {
/*'can_select'(newVal, oldVal) {
......@@ -208,10 +239,10 @@
...mapActions(['openExternalLink']),
whenDirIsOpen(ev, data) {
if (!data) {
this.$store.commit("set", ["can_open_dir", true])
this.$store.commit("set", ["can_open_dir", true]);
} else {
this.$store.commit("set", ["can_open_dir", false])
this.selected_path = data
this.$store.commit("set", ["can_open_dir", false]);
this.selected_path = data;
}
},
......@@ -294,9 +325,29 @@
this.deleteCacheloading = true;
ipcRenderer.send('delete-cache', this.items)
},
set_checkUpdates() {
let data = this.configData;
data.checkUpdates = !data.checkUpdates;
ipcRenderer.send('save-config', data)
if(data.checkUpdates){
ipcRenderer.send('check-for-update', null);
}
}
},
created() {
ipcRenderer.send('get-config', null);
ipcRenderer.send('check-for-update', null);
ipcRenderer.on('config-data', (ev, data) => {
this.configData = data;
// this.$store.commit("set", ['configData', data])
// console.log(this.configData);
});
ipcRenderer.on('open-dir', this.whenDirIsOpen);
ipcRenderer.on('start-read-dir', this.startReadDir);
ipcRenderer.on('read-media-file', this.readFile);
......@@ -317,6 +368,33 @@
ipcRenderer.send('get-cache-size')
});
/*-----------------------------------
Updates
-----------------------------------*/
ipcRenderer.on('need-to-update', (ev, data) => {
let dlink = this.configData.downloadLink + data.hash;
let ver = data.filename_orig.split("_")[1];
this.$q.notify({
message: `<div class="text-subtitle1">New version released <b>v${ver}</b>.</div>
<div class="">Installed v${this.configData.version}</div>`,
multiLine: true,
html: true,
timeout: 0,
progress: true,
// color: 'secondary',
actions: [
{
label: 'Download', color: 'yellow', handler: () => {
this.$store.dispatch("openExternalLink", dlink)
}
},
{
label: 'Dismiss', color: 'white', handler: () => {}
}
]
});
});
}
}
......@@ -435,4 +513,4 @@
}
</style>
\ No newline at end of file
</style>
import ConfigModel from "../../src/models/ConfigModel"
import {Media} from "../../src/models/Media";
import {MainModelClass} from "../../src/models/MainModelClass";
import baseConfig from "../../project.config";
describe('Config class', ()=> {
const O = new ConfigModel();
/**
* Check is config file exists and if is not create it, another say true
*/
test('Load settings', () =>{
let res = O.loadSettings(baseConfig);
expect(res).toBeTruthy();
});
/**
* Get settings
*/
test('Get settings', () =>{
let settings = O.getSettings();
expect(settings).toHaveProperty('version');
})
})
import Updater from "../../src/models/Updater";
import BaseConfig from '../../project.config'
import _ from 'lodash'
describe('Updater class', ()=>{
test('check for new version', ()=>{
return Updater.check(BaseConfig).then(res => {
if(_.isBoolean(res)){
expect(res).toBeFalsy(res);
return;
}
expect(res).toHaveProperty('filename_orig');
console.log(res);
}).catch(err => {
console.log(err);
expect(err).toHaveProperty('message');
});
})
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment