Refactor common code out

This commit is contained in:
lights0123 2020-10-02 16:17:55 -04:00
parent 684b3c3b17
commit 35df1c69f4
No known key found for this signature in database
GPG key ID: 28F315322E37972F
58 changed files with 2713 additions and 209 deletions

View file

@ -10,6 +10,7 @@
},
"dependencies": {
"@tailwindcss/custom-forms": "^0.2.1",
"n-link-core": "0.0.0",
"core-js": "^3.6.5",
"element-ui": "^2.13.2",
"feather-icons": "^4.28.0",

View file

@ -1,9 +1 @@
module.exports = {
plugins: {
tailwindcss: {},
'vue-cli-plugin-tailwind/purgecss': {
whitelistPatternsChildren: [/^el-/],
},
autoprefixer: {}
}
}
module.exports = require('n-link-core/postcss.config');

View file

@ -5,6 +5,7 @@
</template>
<style lang="scss">
@import '~n-link-core/assets/tailwind.css';
#app {
user-select: none;
font-family: Avenir, Helvetica, Arial, sans-serif;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -1,6 +1,7 @@
import {promisified} from 'tauri/api/tauri';
import {listen} from 'tauri/api/event';
import {Component, Vue} from 'vue-property-decorator';
import type {GenericDevices} from 'n-link-core/components/devices';
export type DevId = { address: number; busNumber: number };
@ -116,7 +117,7 @@ async function listAll(dev: DevId | string, path: FileInfo): Promise<FileInfo[]>
let queueId = 0;
@Component
class Devices extends Vue {
class Devices extends Vue implements GenericDevices {
devices: Record<string, Device> = {};
enumerating = false;
hasEnumerated = false;
@ -279,9 +280,3 @@ class Devices extends Vue {
const devices = new Devices();
export default devices;
Vue.prototype.$devices = devices;
declare module 'vue/types/vue' {
// 3. Declare augmentation for Vue
interface Vue {
$devices: Devices;
}
}

View file

@ -2,7 +2,7 @@ import Vue from 'vue'
import App from './App.vue'
import AsyncComputed from 'vue-async-computed';
import router from './router'
import './assets/tailwind.css'
import 'n-link-core/assets/tailwind.css'
import './components/devices';
Vue.use(AsyncComputed);
Vue.config.productionTip = false

View file

@ -35,9 +35,9 @@
<script lang="ts">
import {Component, Vue, Watch} from 'vue-property-decorator';
import {open} from 'tauri/api/window';
import CalcInfo from '@/components/CalcInfo.vue';
import FileBrowser from '@/components/FileBrowser.vue';
import DeviceSelect from "@/components/DeviceSelect.vue";
import CalcInfo from 'n-link-core/components/CalcInfo.vue';
import FileBrowser from 'n-link-core/components/FileBrowser.vue';
import DeviceSelect from "n-link-core/components/DeviceSelect.vue";
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));

View file

@ -1,54 +1 @@
module.exports = {
future: {
purgeLayersByDefault: true,
removeDeprecatedGapUtilities: true,
},
theme: {
fontFamily: {
sans: [
'Cantarell',
'Roboto',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'"Helvetica Neue"',
'Arial',
'"Noto Sans"',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
'"Noto Color Emoji"',
],
},
extend: {
inset: {
'1/8': '0.125em',
},
boxShadow: {
even: '0 2px 12px 0 #0000001a',
error: '0 0 0 3px #F56C6CA0',
},
padding: {
'2.5': '0.625em',
'3/2': '0.375em',
},
colors: {
ui: {
background: 'var(--color-ui-background)',
emph: 'var(--color-ui-emph)',
sidebar: 'var(--color-ui-sidebar)',
text: 'var(--color-ui-text)',
'text-inv': 'var(--color-ui-text-inv)',
primary: 'var(--color-ui-primary)',
border: 'var(--color-ui-border)',
blockquote: 'var(--color-ui-blockquote)',
},
},
},
},
variants: {},
plugins: [require('@tailwindcss/custom-forms')],
purge: false,
};
module.exports = require('n-link-core/tailwind.config');

3
desktop/vue.config.js Normal file
View file

@ -0,0 +1,3 @@
module.exports = {
transpileDependencies: ['n-link-core']
}

18
n-link-core/.eslintrc.js Normal file
View file

@ -0,0 +1,18 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended',
'@vue/typescript/recommended'
],
parserOptions: {
ecmaVersion: 2020
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? ['warn', { allow: ['warn', 'error'] }] : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}

View file

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View file

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View file

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View file

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View file

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -38,7 +38,7 @@
<script lang="ts">
import {Component, Prop, Vue} from 'vue-property-decorator';
import type {Info, Version} from '@/components/devices';
import type {Info, Version} from './devices';
import fileSize from "filesize";
@Component

View file

@ -38,7 +38,7 @@
import {Component, Prop, Vue} from 'vue-property-decorator';
import ElPopover from 'element-ui/packages/popover/src/main.vue';
import 'element-ui/lib/theme-chalk/popover.css';
import {Device} from "@/components/devices";
import type {Device} from "./devices";
function getCoordinatesForPercent(percent: number) {
const x = Math.cos(2 * Math.PI * percent);

View file

@ -28,10 +28,10 @@
<script lang="ts">
import {Component, Prop, Vue, Watch} from 'vue-property-decorator';
import FileView from '@/components/FileView.vue';
import type {FileInfo} from "@/components/devices";
import FileData from "@/components/FileData.vue";
import DeviceQueue from "@/components/DeviceQueue.vue";
import FileView from './FileView.vue';
import type {FileInfo} from "./devices";
import FileData from "./FileData.vue";
import DeviceQueue from "./DeviceQueue.vue";
@Component({
asyncComputed: {

View file

@ -77,8 +77,8 @@ import {Component, Prop, Vue} from 'vue-property-decorator';
import ElPopover from 'element-ui/packages/popover/src/main.vue';
import 'element-ui/lib/theme-chalk/popover.css';
import fileSize from "filesize";
import type {FileInfo} from '@/components/devices';
import FileIcon from "@/components/FileIcon.vue";
import type {FileInfo} from './devices';
import FileIcon from "./FileIcon.vue";
@Component({
components: {FileIcon, ElPopover}

View file

@ -26,59 +26,59 @@ export default class FileView extends Vue {
if (this.dir) {
switch (this.name.trim().toLowerCase()) {
case 'games':
return require('@/assets/folders/games.svg');
return require('../assets/folders/games.svg');
case 'images':
case 'photos':
return require('@/assets/folders/images.svg');
return require('../assets/folders/images.svg');
case 'music':
case 'sound':
case 'sounds':
return require('@/assets/folders/music.svg');
return require('../assets/folders/music.svg');
case 'script':
case 'scripts':
case 'program':
case 'programs':
return require('@/assets/folders/scripts.svg');
return require('../assets/folders/scripts.svg');
case 'template':
case 'templates':
return require('@/assets/folders/templates.svg');
return require('../assets/folders/templates.svg');
case 'video':
case 'videos':
return require('@/assets/folders/video.svg');
return require('../assets/folders/video.svg');
default:
return require('@/assets/folders/folder.svg');
return require('../assets/folders/folder.svg');
}
}
if (this.name === 'ndless_resources.tns') return require('@/assets/files/resources.svg');
if (this.name.startsWith('ndless_installer')) return require('@/assets/files/installer.svg');
if (this.name === 'ndless_resources.tns') return require('../assets/files/resources.svg');
if (this.name.startsWith('ndless_installer')) return require('../assets/files/installer.svg');
switch (this.ext.toLowerCase()) {
case 'bin':
return require('@/assets/files/binary.svg');
return require('../assets/files/binary.svg');
case 'ical':
case 'ics':
case 'ifb':
case 'icalendar':
return require('@/assets/files/calendar.svg');
return require('../assets/files/calendar.svg');
case 'cfg':
return require('@/assets/files/cfg.svg');
return require('../assets/files/cfg.svg');
case 'vcf':
return require('@/assets/files/contact.svg');
return require('../assets/files/contact.svg');
case 'csv':
case 'log':
case 'logs':
return require('@/assets/files/csv.svg');
return require('../assets/files/csv.svg');
case 'sql':
case 'db':
case 'sqlite':
return require('@/assets/files/db.svg');
return require('../assets/files/db.svg');
case 'epub':
return require('@/assets/files/epub.svg');
return require('../assets/files/epub.svg');
case 'eot':
case 'otf':
case 'ttf':
case 'woff':
case 'woff2':
return require('@/assets/files/font.svg');
return require('../assets/files/font.svg');
case 'png':
case 'bmp':
case 'jpg':
@ -117,41 +117,41 @@ export default class FileView extends Vue {
case 'tga':
case 'psd':
case 'xcf':
return require('@/assets/files/image.svg');
return require('../assets/files/image.svg');
case 'js':
case 'mjs':
return require('@/assets/files/js.svg');
return require('../assets/files/js.svg');
case 'json':
case 'json5':
return require('@/assets/files/json.svg');
return require('../assets/files/json.svg');
case 'lua':
return require('@/assets/files/lua.svg');
return require('../assets/files/lua.svg');
case 'pdf':
return require('@/assets/files/pdf.svg');
return require('../assets/files/pdf.svg');
case 'py':
return require('@/assets/files/python.svg');
return require('../assets/files/python.svg');
case 'rom':
case '89u':
case 'smc':
case 'sfc':
case 'srm':
case 'img':
return require('@/assets/files/rom.svg');
return require('../assets/files/rom.svg');
case 'svg':
case 'svgz':
return require('@/assets/files/svg.svg');
return require('../assets/files/svg.svg');
case 'txt':
return require('@/assets/files/txt.svg');
return require('../assets/files/txt.svg');
case 'mp4':
return require('@/assets/files/video.svg');
return require('../assets/files/video.svg');
case 'xml':
return require('@/assets/files/xml.svg');
return require('../assets/files/xml.svg');
case 'zip':
case 'tar':
case 'gz':
return require('@/assets/files/zip.svg');
return require('../assets/files/zip.svg');
default:
return require('@/assets/files/unknown.svg');
return require('../assets/files/unknown.svg');
}
}
}

View file

@ -12,8 +12,8 @@
<script lang="ts">
import {Component, Prop, Vue, Watch} from 'vue-property-decorator';
import type {FileInfo} from '@/components/devices';
import FileIcon from "@/components/FileIcon.vue";
import type {FileInfo} from './devices';
import FileIcon from "./FileIcon.vue";
@Component({
components: {FileIcon}

View file

@ -0,0 +1,64 @@
export type DevId = { address: number; busNumber: number };
export type Version = { major: number; minor: number; patch: number; build: number };
export type Lcd = { width: number; height: number; bpp: number; sample_mode: number };
export type HardwareType =
| "Cas"
| "NonCas"
| "CasCx"
| "NonCasCx"
| { Unknown: number };
// The current state of the calculator.
export type RunLevel =
| "Recovery"
| "Os"
| { Unknown: number };
export type Battery =
| "Powered"
| "Low"
| "Ok"
| { Unknown: number };
export type Info = { free_storage: number; total_storage: number; free_ram: number; total_ram: number; version: Version; boot1_version: Version; boot2_version: Version; hw_type: HardwareType; clock_speed: number; lcd: Lcd; os_extension: string; file_extension: string; name: string; id: string; run_level: RunLevel; battery: Battery; is_charging: boolean };
export type FileInfo = { path: string; isDir: boolean; date: number; size: number };
export type Progress = { remaining: number; total: number };
export type PartialCmd = { action: 'download'; path: [string, number]; dest: string }
| { action: 'upload'; path: string; src: string }
| { action: 'uploadOs'; src: string }
| { action: 'deleteFile'; path: string }
| { action: 'deleteDir'; path: string }
| { action: 'createDir'; path: string }
| { action: 'move'; src: string; dest: string }
| { action: 'copy'; src: string; dest: string };
export type Cmd = { id: number } & PartialCmd;
export type Device = { name: string; isCxIi: boolean; needsDrivers: boolean; info?: Info; progress?: Progress; queue?: Cmd[]; running?: boolean };
export interface GenericDevices {
devices: Record<string, Device>;
enumerating: boolean;
hasEnumerated: boolean;
enumerate(): Promise<void>;
open(dev: string): Promise<void>;
close(dev: string): Promise<void>;
update(dev: string): Promise<void>;
listDir(dev: DevId | string, path: string): Promise<FileInfo[]>;
promptUploadFiles(dev: DevId | string, path: string): Promise<void>;
uploadOs(dev: DevId | string, filter: string): Promise<void>;
downloadFiles(dev: DevId | string, files: [string, number][]): Promise<void>;
delete(dev: DevId | string, files: FileInfo[]): Promise<void>;
createDir(dev: DevId | string, path: string): Promise<void>;
copy(dev: DevId | string, src: string, dest: string): Promise<void>;
move(dev: DevId | string, src: string, dest: string): Promise<void>;
}
declare module 'vue/types/vue' {
// 3. Declare augmentation for Vue
interface Vue {
$devices: GenericDevices;
}
}

View file

@ -0,0 +1,9 @@
module.exports = {
plugins: {
tailwindcss: {},
'vue-cli-plugin-tailwind/purgecss': {
whitelistPatternsChildren: [/^el-/],
},
autoprefixer: {}
}
}

13
n-link-core/shims-tsx.d.ts vendored Normal file
View file

@ -0,0 +1,13 @@
import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}

54
n-link-core/shims-vue.d.ts vendored Normal file
View file

@ -0,0 +1,54 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
import Vue, { PluginFunction } from 'vue';
interface IAsyncComputedOptions {
errorHandler?: (error: string[]) => void;
useRawError?: boolean;
default?: any;
}
export default class AsyncComputed {
constructor(options?: IAsyncComputedOptions);
static install: PluginFunction<never>;
static version: string;
}
type AsyncComputedGetter<T> = () => Promise<T> | T;
export interface IAsyncComputedProperty<T> {
default?: T | (() => T);
get: AsyncComputedGetter<T>;
watch?: () => void;
shouldUpdate?: () => boolean;
lazy?: boolean;
}
interface IAsyncComputedProperties {
[K: string]: AsyncComputedGetter<any> | IAsyncComputedProperty<any>;
}
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
// @ts-ignore
asyncComputed?: IAsyncComputedProperties;
}
}
interface IASyncComputedState {
state: 'updating' | 'success' | 'error';
updating: boolean;
success: boolean;
error: boolean;
exception: Error | null;
update: () => void;
}
declare module 'vue/types/vue' {
// tslint:disable-next-line:interface-name
interface Vue {
$asyncComputed: { [K: string]: IASyncComputedState };
}
}

View file

@ -0,0 +1,54 @@
module.exports = {
future: {
purgeLayersByDefault: true,
removeDeprecatedGapUtilities: true,
},
theme: {
fontFamily: {
sans: [
'Cantarell',
'Roboto',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'"Helvetica Neue"',
'Arial',
'"Noto Sans"',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
'"Noto Color Emoji"',
],
},
extend: {
inset: {
'1/8': '0.125em',
},
boxShadow: {
even: '0 2px 12px 0 #0000001a',
error: '0 0 0 3px #F56C6CA0',
},
padding: {
'2.5': '0.625em',
'3/2': '0.375em',
},
colors: {
ui: {
background: 'var(--color-ui-background)',
emph: 'var(--color-ui-emph)',
sidebar: 'var(--color-ui-sidebar)',
text: 'var(--color-ui-text)',
'text-inv': 'var(--color-ui-text-inv)',
primary: 'var(--color-ui-primary)',
border: 'var(--color-ui-border)',
blockquote: 'var(--color-ui-blockquote)',
},
},
},
},
variants: {},
plugins: [require('@tailwindcss/custom-forms')],
purge: false,
};

39
n-link-core/tsconfig.json Normal file
View file

@ -0,0 +1,39 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"./*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"./**/*.ts",
"./**/*.tsx",
"./**/*.vue"
],
"exclude": [
"node_modules"
],
"typeRoots": ["@/types", "./node_modules/@types"]
}

View file

@ -1,6 +1,11 @@
{
"private": true,
"workspaces": [
"desktop"
]
"desktop",
"n-link-core",
"web"
],
"dependencies": {
"@vue/cli-plugin-eslint": "~4.5.0"
}
}

2495
yarn.lock

File diff suppressed because it is too large Load diff