Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Feature(settings): log file path setting and reveal file #108

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/utils/message-method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ export enum W2VMessage {
EXECUTE_COMMAND = 'EXECUTE_COMMAND',
GET_ALL_UPLOADERS = 'GET_ALL_UPLOADERS',
GET_ALL_UPLOADER_CONFIGS = 'GET_ALL_UPLOADER_CONFIGS',
SET_CONFIG = 'SET_CONFIG'
SET_CONFIG = 'SET_CONFIG',
REVEAL_FILE_IN_OS = 'REVEAL_FILE_IN_OS',
GET_PICGO_SETTINGS = 'GET_PICGO_SETTINGS'
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/vscode/CommandManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ export class CommandManager {
const pluginName = 'vspicgo'
PicgoAPI.picgoAPI.setCurrentPluginName(pluginName)
const [id, plugin] = PicgoAddon.picgoAddon.beforeUploadPlugin()
PicgoAPI.picgoAPI.helper.beforeUploadPlugins.register(id, plugin)
PicgoAPI.picgoAPI.picgo.helper.beforeUploadPlugins.register(id, plugin)

const output = await PicgoAPI.picgoAPI.upload(input)
PicgoAPI.picgoAPI.helper.beforeUploadPlugins.unregister(pluginName)
PicgoAPI.picgoAPI.picgo.helper.beforeUploadPlugins.unregister(pluginName)

// error has been handled in picgoAPI.upload
if (!output) return
Expand Down
48 changes: 34 additions & 14 deletions src/vscode/PicgoAPI.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,52 @@
import { IConfig, PicGo, IHelper, LifecyclePlugins, IPluginConfig } from 'picgo'
import { IConfig, PicGo, LifecyclePlugins, IPluginConfig } from 'picgo'
import { DataStore } from './DataStore'
import vscode from 'vscode'
import { decorateMessage, showError, showInfo } from './utils'
import { defaultSettings } from './settings'
import _ from 'lodash-es'
import { defaultSettings, IPicGoSettings } from './settings'
import _, { isObject } from 'lodash-es'
import { Get } from 'type-fest'
export type GetConfig<T extends string> = Get<IConfig, T>

export interface IUploaderConfig {
uploaderName: string
uploaderID: string
/**
* The current list of all configurations of the uploader. An uploader will have a `IPlugin.config` function to determine the current configurations. Usually it will be calculated as something like `default: userConfig.xxx || 'github'`, that is, read the picgo core configuration first and set something as fallback
*/
configList?: IPluginConfig[]
}

export class PicgoAPI {
static picgoAPI = new PicgoAPI()

private readonly picgo: PicGo
helper: IHelper
readonly picgo: PicGo
constructor() {
this.picgo = new PicGo(DataStore.dataStore.configPath)
this.picgo.saveConfig({
debug: true
})
this.initConfig()
this.helper = this.picgo.helper
}

initConfig() {
this.setConfigIfNotExist(
'settings.vsPicgo.customOutputFormat',
defaultSettings.settings.vsPicgo.customOutputFormat
)
this.setConfigIfNotExist(
'settings.vsPicgo.customUploadName',
defaultSettings.settings.vsPicgo.customUploadName
)
const dfs = (val: any, path: string[]) => {
if (isObject(val)) {
for (const key of Object.keys(val)) {
dfs((val as any)[key], [...path, key])
}
} else {
// Leaf condition is a non-object value, we init this value if it does not exist in the config file
this.setConfigIfNotExist(path.join('.'), val)
// for example:
// this.setConfigIfNotExist(
// 'settings.vsPicgo.customOutputFormat',
// defaultSettings.settings.vsPicgo.customOutputFormat
// )
}
}

// Init all values in the `defaultSettings` object
dfs(defaultSettings, [])
}

setConfigIfNotExist<T extends string>(configName: T, value: GetConfig<T>) {
Expand Down Expand Up @@ -93,6 +104,15 @@ export class PicgoAPI {
})
}

getPicGoSettings(): IPicGoSettings {
const config = this.picgo.getConfig<IPicGoSettings>()
// Although there is no configuration in the config file, we should let user know the current default log level and log path etc.
config.settings.logLevel ??= this.picgo.log.logLevel
config.settings.logPath ??= this.picgo.log.logPath

return config
}

/**
* @param input This image file paths to be uploaded, will upload from clipboard if no input specified
*/
Expand Down
23 changes: 17 additions & 6 deletions src/vscode/settings.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
/* eslint-disable no-template-curly-in-string */
export interface IPicgoSettings {
import { PartialDeep } from 'type-fest'
import { IConfig, LogLevel } from 'picgo'
/**
* All this settings are configurable in the settings page of the picgo control panel
*/
export interface IPicGoSettings extends IConfig {
settings: {
vsPicgo: {
customUploadName: string
customOutputFormat: string
}
logLevel: LogLevel | LogLevel[]
logPath: string
}
picBed: {
current: string
uploader: string
}
}

// TODO: add a select in settings page for user to select this presets
export const outputFormats = {
Markdown: '![${uploadedName}](${url})',
HTML: '<img src="${url}" alt="${uploadedName}">',
Expand All @@ -16,17 +28,16 @@ export const outputFormats = {
}

export const uploadName = {
auto:
SelectionOrOriginalName:
'${editorSelectionText ? `${editorSelectionText}${imgIdx}` : fileName}${extName}',
dateExt: '${date}${extName}'
Date: '${date}${extName}'
}

export const defaultSettings: IPicgoSettings = {
export const defaultSettings: PartialDeep<IPicGoSettings> = {
settings: {
vsPicgo: {
customOutputFormat: outputFormats.Markdown,
customUploadName:
'${editorSelectionText ? `${editorSelectionText}${imgIdx}` : fileName}${extName}'
customUploadName: uploadName.SelectionOrOriginalName
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/vscode/utils/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,16 @@ export const getChannel = (
}
)

channel.bind<string>(W2VMessage.REVEAL_FILE_IN_OS, async (path) => {
return await vscode.commands.executeCommand(
'revealFileInOS',
vscode.Uri.file(path)
)
})

channel.bind(W2VMessage.GET_PICGO_SETTINGS, () => {
return PicgoAPI.picgoAPI.getPicGoSettings()
})

return channel
}
15 changes: 14 additions & 1 deletion src/webview/pages/PicGoControlPanel/PicGoDrawerList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const PicGoDrawerList = () => {
my: 0.5
}}>
<ListItemIcon>
<MuiIconsMaterial.Settings />
<MuiIconsMaterial.Cloud />
</ListItemIcon>
<ListItemText primary="Uploaders" />
{uploaderListOpened ? (
Expand All @@ -86,6 +86,19 @@ export const PicGoDrawerList = () => {
))}
</List>
</Collapse>

<ListItemButton
onClick={() => history.push('/settings/vs-picgo')}
selected={pathname === '/settings/vs-picgo'}
sx={{
borderRadius: 4,
my: 0.5
}}>
<ListItemIcon>
<MuiIconsMaterial.Settings />
</ListItemIcon>
<ListItemText primary="Settings" />
</ListItemButton>
</List>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
Grid,
Paper,
TextField,
Select,
MenuItem,
Typography,
Box,
Expand Down Expand Up @@ -84,12 +83,15 @@ export const PicGoPluginConfigForm: React.FC<IPicGoPluginConfigFormProps> = ({
/>
}
label={config.name}
sx={{
my: 1
}}
/>
)
case 'list':
case 'checkbox':
return (
<Select
<TextField
fullWidth
key={config.name}
label={config.name}
Expand All @@ -98,6 +100,7 @@ export const PicGoPluginConfigForm: React.FC<IPicGoPluginConfigFormProps> = ({
}}
placeholder={config.message ?? config.name}
required={config.required}
select
sx={{
my: 1
}}
Expand All @@ -110,7 +113,7 @@ export const PicGoPluginConfigForm: React.FC<IPicGoPluginConfigFormProps> = ({
</MenuItem>
)
})}
</Select>
</TextField>
)
default:
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react'
import { useRouteMatch } from 'react-router'
import {
Grid,
Paper,
FormControl,
InputLabel,
OutlinedInput,
InputAdornment,
IconButton
} from '@mui/material'
import * as MuiIconsMaterial from '@mui/icons-material'
import { useAsync } from 'react-use'
import { useDispatch, useState } from '../hooks'
import {
getPicGoSettings,
revealFileInOS,
setConfig
} from '../../../utils/channel'

/**
* This page contains all the settings in the IPicgoSettings.settings.vsPicgo, and application wide configuration such current uploader in the `picBed.uploader` field
*/
export const VSPicGoSettings: React.FC = () => {
const match = useRouteMatch('/settings/vs-picgo')
if (!match) return null

const dispatch = useDispatch('settings')
useAsync(async () => {
dispatch.setPicGoSettings(await getPicGoSettings())
}, [])

const { picgoSettings } = useState('settings')

return (
<Grid
item
lg={9}
md={8}
sx={{
textAlign: 'center'
}}
xs={12}>
<Paper
sx={{
p: 2
}}>
{/* Log file settings */}
<FormControl fullWidth sx={{ my: 1 }} variant="outlined">
<InputLabel htmlFor="log-file-path">Log file path</InputLabel>
<OutlinedInput
endAdornment={
<InputAdornment position="end">
<IconButton
edge="end"
onClick={() => {
const logPath = picgoSettings?.settings.logPath
if (!logPath) return
revealFileInOS(logPath)
}}
title="Reveal log file in system file explorer">
<MuiIconsMaterial.FolderOpen />
</IconButton>
</InputAdornment>
}
fullWidth
id="log-file-path"
label="Log file path"
onChange={async (e) => {
await setConfig('settings.logPath', e.target.value)
dispatch.setPicGoSettings(await getPicGoSettings())
}}
value={picgoSettings?.settings.logPath ?? 'N/A'}
/>
</FormControl>
</Paper>
</Grid>
)
}
3 changes: 3 additions & 0 deletions src/webview/pages/PicGoControlPanel/PicGoSettings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react'
import { PicGoPluginConfigForm } from './PicGoPluginConfigForm'
import { useState, useDispatch } from '../hooks'
import { useParams } from 'react-router-dom'
import { VSPicGoSettings } from './VSPicGoSettings'

export interface IPicGoSettingsParams {
uploaderID?: string
Expand All @@ -17,6 +18,8 @@ export const PicGoSettings: React.FC = () => {

return (
<Grid container justifyContent="center" spacing={3}>
{/* This vs-picgo Settings page */}
<VSPicGoSettings />
{/* If it is a uploader config page */}
{params.uploaderID
? (() => {
Expand Down
3 changes: 3 additions & 0 deletions src/webview/pages/PicGoControlPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export const PicGoControlPanelInner = () => {
<Route exact path={`/settings/uploader/:uploaderID`}>
<PicGoSettings />
</Route>
<Route exact path={`/settings/vs-picgo`}>
<PicGoSettings />
</Route>
<Route exact path={`/settings/plugin/:pluginID`}>
<PicGoSettings />
</Route>
Expand Down
13 changes: 10 additions & 3 deletions src/webview/pages/PicGoControlPanel/models/settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createModel } from '@rematch/core'
import type { IUploaderConfig } from '../../../../vscode/PicgoAPI'
import type { IPicGoSettings } from '../../../../vscode/settings'
import { IRootModel } from '../models'
import { setConfig } from '../../../utils/channel'
export interface IPicGoSettingState {
Expand All @@ -13,6 +14,7 @@ export interface IPicGoSettingState {
* currentUploaderConfigs[uploaderID][config.name] = value
*/
currentUploaderConfigs: Record<string, Record<string, any>>
picgoSettings: IPicGoSettings | null
}

export interface IUpdateCurrentUploaderConfigsPayload {
Expand All @@ -21,13 +23,14 @@ export interface IUpdateCurrentUploaderConfigsPayload {
value: any
}

export const defaultCommonState: IPicGoSettingState = {
export const defaultSettingsState: IPicGoSettingState = {
allUploaderConfigs: [],
currentUploaderConfigs: {}
currentUploaderConfigs: {},
picgoSettings: null
}

export const settings = createModel<IRootModel>()({
state: defaultCommonState,
state: defaultSettingsState,
reducers: {
/**
* This reducer should be called on paged loaded so that we have the initial `currentUploaderConfigs` state for page to render correctly, such as the uploader list in the drawer and the whole settings page.
Expand All @@ -51,6 +54,10 @@ export const settings = createModel<IRootModel>()({
) {
setConfig(`picBed.${uploaderID}.${configName}`, value)
state.currentUploaderConfigs[uploaderID][configName] = value
},

setPicGoSettings(state, picgoSettings: IPicGoSettings) {
state.picgoSettings = picgoSettings
}
},
selectors: (slice, createSelector, hasProps) => ({
Expand Down
Loading