Merge branch 'fun-with-browsers' of https://github.com/hearmeneigh/fchat-rising into fun-with-browsers
This commit is contained in:
commit
fb5cec06ba
|
@ -127,7 +127,10 @@ export class BBCodeParser {
|
|||
isAllowed = (name) => self.isAllowed(name) && parentAllowed(name);
|
||||
currentTag = this._currentTag = {tag: self.tag, line: this._line, column: this._column};
|
||||
}
|
||||
let tagStart = -1, paramStart = -1, mark = start;
|
||||
let tagStart = -1,
|
||||
paramStart = -1,
|
||||
mark = start,
|
||||
isInCollapseParam = false;
|
||||
for(let i = start; i < input.length; ++i) {
|
||||
const c = input[i];
|
||||
++this._column;
|
||||
|
@ -135,12 +138,22 @@ export class BBCodeParser {
|
|||
++this._line;
|
||||
this._column = 1;
|
||||
}
|
||||
if(c === '[') {
|
||||
if(c === '[' && !isInCollapseParam) {
|
||||
tagStart = i;
|
||||
paramStart = -1;
|
||||
} else if(c === '=' && paramStart === -1)
|
||||
paramStart = i;
|
||||
} else if(c === '=' && paramStart === -1) {
|
||||
paramStart = i;
|
||||
|
||||
const paramIndex = paramStart === -1 ? i : paramStart;
|
||||
let tagKey = input
|
||||
.substring(tagStart + 1, paramIndex)
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
if (tagKey == "collapse") isInCollapseParam = true;
|
||||
}
|
||||
else if(c === ']') {
|
||||
|
||||
const paramIndex = paramStart === -1 ? i : paramStart;
|
||||
let tagKey = input.substring(tagStart + 1, paramIndex).trim().toLowerCase();
|
||||
if(tagKey.length === 0) {
|
||||
|
@ -154,6 +167,17 @@ export class BBCodeParser {
|
|||
tagStart = -1;
|
||||
continue;
|
||||
}
|
||||
if (isInCollapseParam) {
|
||||
let fullTagKey = input
|
||||
.substring(tagStart + 1, i + 1)
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
if (fullTagKey.endsWith("[hr]")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
isInCollapseParam = false;
|
||||
if(!close) {
|
||||
const tag = this._tags[tagKey]!;
|
||||
const allowed = isAllowed(tagKey);
|
||||
|
|
|
@ -72,8 +72,15 @@ export class StandardBBCodeParser extends CoreBBCodeParser {
|
|||
const icon = parser.createElement('i');
|
||||
icon.className = 'fas fa-chevron-down';
|
||||
icon.style.marginRight = '10px';
|
||||
headerText.appendChild(icon);
|
||||
headerText.appendChild(document.createTextNode(param));
|
||||
// HACK: to allow [hr] in header part
|
||||
if (param.startsWith('[hr]')) { headerText.appendChild(parser.createElement('hr')); param = param.slice(4) }
|
||||
headerText.appendChild(icon);
|
||||
const splitParam = param.split('[hr]')
|
||||
for (let iii = 0; iii < splitParam.length; iii++) {
|
||||
const element = splitParam[iii];
|
||||
headerText.appendChild(document.createTextNode(element));
|
||||
if (iii < splitParam.length-1) headerText.appendChild(parser.createElement('hr'))
|
||||
}
|
||||
outer.appendChild(headerText);
|
||||
const body = parser.createElement('div');
|
||||
body.className = 'bbcode-collapse-body';
|
||||
|
|
|
@ -197,6 +197,7 @@ Current log location: {1}`,
|
|||
'settings.browserOptionArgumentsHelp': 'Arguments are separated by spaces. Use %s to insert the URL.',
|
||||
'settings.browserOptionBrowse': 'Browse',
|
||||
'settings.browserOptionSave': 'Save',
|
||||
'settings.browserOptionReset': 'Reset to default',
|
||||
'fixLogs.action': 'Fix corrupted logs',
|
||||
'fixLogs.text': `There are a few reason log files can become corrupted - log files from old versions with bugs that have since been fixed or incomplete file operations caused by computer crashes are the most common.
|
||||
If one of your log files is corrupted, you may get an "Unknown Type" error when you log in or when you open a specific tab. You may also experience other issues.
|
||||
|
|
|
@ -16,6 +16,21 @@
|
|||
<div class="card bg-light" style="height:100%;width:100%;">
|
||||
<div class="card-body row" style="height:100%;width:100%;">
|
||||
<h4 class="card-title">{{l('settings.browserOptionTitle')}}</h4>
|
||||
<div class="form-group col-12">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="warning">
|
||||
<h5>Danger Zone!</h5>
|
||||
<div>This is an advanced setting. By changing this setting to an unsupported program (i.e. not a browser), you might not be able to open links from F-Chat anymore.</div>
|
||||
|
||||
<div v-if="isMac"><hr/>
|
||||
<p>Mac User: As of writing, MacOS has a bug in how it handles opening links.</p>
|
||||
<p>When your default browser is something other than Safari and you select Safari in this settings window, links might be opened twice.</p>
|
||||
<p>Once in Safari and a second time in your default browser. This tends to happen when Safari is not running when clicking a link.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<label class="control-label" for="browserPath">{{l('settings.browserOptionPath')}}</label>
|
||||
<div class="row">
|
||||
|
@ -41,9 +56,13 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<div class="row">
|
||||
<div class="row no-gutters">
|
||||
<div class="col-2">
|
||||
<button class="btn btn-primary" @click.prevent.stop="submit()">{{l('settings.browserOptionSave')}}</button>
|
||||
<button class="btn btn-primary" @click.prevent.stop="submit()">{{l('settings.browserOptionSave')}}</button>
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
<div class="col-4">
|
||||
<button class="btn btn-danger" style="float: right;" @click.prevent.stop="resetToDefault()">{{l('settings.browserOptionReset')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,6 +102,7 @@ export default class BrowserOption extends Vue {
|
|||
hasCompletedUpgrades = false;
|
||||
browserPath = '';
|
||||
browserArgs = '';
|
||||
isMac = process.platform === 'darwin';
|
||||
|
||||
get styling(): string {
|
||||
try {
|
||||
|
@ -144,6 +164,11 @@ export default class BrowserOption extends Vue {
|
|||
this.close();
|
||||
}
|
||||
|
||||
resetToDefault(): void {
|
||||
this.browserPath = '';
|
||||
this.browserArgs = '';
|
||||
}
|
||||
|
||||
browseForPath(): void {
|
||||
ipcRenderer.invoke('browser-option-browse').then((result) => {
|
||||
this.browserPath = result;
|
||||
|
@ -197,6 +222,16 @@ export default class BrowserOption extends Vue {
|
|||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
border: 1px solid var(--warning);
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 3px;
|
||||
|
||||
div {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.disableWindowsHighContrast, .disableWindowsHighContrast * {
|
||||
forced-color-adjust: none;
|
||||
|
|
|
@ -173,26 +173,53 @@ async function addSpellcheckerItems(menu: electron.Menu): Promise<void> {
|
|||
}
|
||||
|
||||
function openURLExternally(linkUrl: string): void {
|
||||
// check if user set a path, whether it exists and if it is a file
|
||||
if(settings.browserPath !== '' &&
|
||||
fs.existsSync(settings.browserPath) &&
|
||||
fs.lstatSync(settings.browserPath).isFile()) {
|
||||
// encode URL so if it contains spaces, it remains a single argument for the browser
|
||||
linkUrl = encodeURI(linkUrl);
|
||||
|
||||
if(!settings.browserArgs.includes('%s')) {
|
||||
// append %s to params if it is not already there
|
||||
settings.browserArgs += ' %s';
|
||||
// check if user set a path and whether it exists
|
||||
const pathIsValid = (settings.browserPath !== '' && fs.existsSync(settings.browserPath));
|
||||
|
||||
if(pathIsValid) {
|
||||
// also check if the user can execute whatever is located at the selected path
|
||||
let fileIsExecutable = false;
|
||||
try {
|
||||
fs.accessSync(settings.browserPath, fs.constants.X_OK);
|
||||
fileIsExecutable = true;
|
||||
} catch (err) {
|
||||
log.error(`Selected browser is not executable by user. Path: "${settings.browserPath}"`);
|
||||
}
|
||||
|
||||
// replace %s in arguments with URL and encapsulate in quotes to prevent issues with spaces and special characters in the path
|
||||
let link = settings.browserArgs.replace('%s', '\"'+linkUrl+'\"');
|
||||
if (fileIsExecutable) {
|
||||
// check if URL is already encoded
|
||||
// (this should work almost all the time, but there might be edge-cases with very unusual URLs)
|
||||
let isEncoded = (linkUrl !== decodeURI(linkUrl));
|
||||
// only encode URL if it isn't encoded yet
|
||||
if (!isEncoded) {
|
||||
// encode URL so if it contains spaces, it remains a single argument for the browser
|
||||
linkUrl = encodeURI(linkUrl);
|
||||
}
|
||||
|
||||
const execFile = require('child_process').exec;
|
||||
execFile(`"${settings.browserPath}" ${link}`);
|
||||
} else {
|
||||
electron.shell.openExternal(linkUrl);
|
||||
if (!settings.browserArgs.includes('%s')) {
|
||||
// append %s to params if it is not already there
|
||||
settings.browserArgs += ' %s';
|
||||
}
|
||||
|
||||
// replace %s in arguments with URL and encapsulate in quotes to prevent issues with spaces and special characters in the path
|
||||
let link = settings.browserArgs.replace('%s', '\"' + linkUrl + '\"');
|
||||
|
||||
const execFile = require('child_process').exec;
|
||||
if (process.platform === "darwin") {
|
||||
// NOTE: This is seemingly bugged on MacOS when setting Safari as the external browser while using a different default browser.
|
||||
// In that case, this will open the URL in both the selected application AND the default browser.
|
||||
// Other browsers work fine. (Tested with Chrome with Firefox as the default browser.)
|
||||
// https://developer.apple.com/forums/thread/685385
|
||||
execFile(`open -a "${settings.browserPath}" ${link}`);
|
||||
} else {
|
||||
execFile(`"${settings.browserPath}" ${link}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
electron.shell.openExternal(linkUrl);
|
||||
}
|
||||
|
||||
function setUpWebContents(webContents: electron.WebContents): void {
|
||||
|
@ -315,17 +342,22 @@ function showPatchNotes(): void {
|
|||
}
|
||||
|
||||
function openBrowserSettings(): electron.BrowserWindow | undefined {
|
||||
let desiredHeight = 520;
|
||||
if(process.platform === 'darwin') {
|
||||
desiredHeight = 750;
|
||||
}
|
||||
|
||||
const windowProperties: electron.BrowserWindowConstructorOptions = {
|
||||
center: true,
|
||||
show: false,
|
||||
icon: process.platform === 'win32' ? winIcon : pngIcon,
|
||||
frame: false,
|
||||
width: 500,
|
||||
height: 350,
|
||||
minWidth: 500,
|
||||
minHeight: 368,
|
||||
maxWidth: 500,
|
||||
maxHeight: 368,
|
||||
width: 650,
|
||||
height: desiredHeight,
|
||||
minWidth: 650,
|
||||
minHeight: desiredHeight,
|
||||
maxWidth: 650,
|
||||
maxHeight: desiredHeight,
|
||||
maximizable: false,
|
||||
webPreferences: {
|
||||
webviewTag: true, nodeIntegration: true, nodeIntegrationInWorker: true, spellcheck: true,
|
||||
|
@ -736,11 +768,23 @@ function onReady(): void {
|
|||
electron.ipcMain.handle('browser-option-browse', async () => {
|
||||
log.debug('settings.browserOption.browse');
|
||||
console.log('settings.browserOption.browse', JSON.stringify(settings));
|
||||
|
||||
let filters;
|
||||
if(process.platform === "win32") {
|
||||
filters = [{ name: 'Executables', extensions: ['exe'] }];
|
||||
} else if (process.platform === "darwin") {
|
||||
filters = [{ name: 'Executables', extensions: ['app'] }];
|
||||
} else {
|
||||
// linux and anything else that might be supported
|
||||
// no specific extension for executables
|
||||
filters = [{ name: 'Executables', extensions: ['*'] }];
|
||||
}
|
||||
|
||||
const dir = electron.dialog.showOpenDialogSync(
|
||||
{
|
||||
defaultPath: settings.browserPath,
|
||||
properties: ['openFile'],
|
||||
filters: [{ name: 'Executables', extensions: ['exe'] }]
|
||||
filters: filters
|
||||
});
|
||||
if(dir !== undefined) {
|
||||
return dir[0];
|
||||
|
|
|
@ -82,3 +82,13 @@ export function init(s: Settings, c: SimpleCharacter[]): void {
|
|||
settings = s;
|
||||
characters = c;
|
||||
}
|
||||
|
||||
function escapeRegExp(string: string):
|
||||
string {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
|
||||
}
|
||||
|
||||
export function replaceAll(str: string, find: string, replace: string):
|
||||
string {
|
||||
return str.replace(new RegExp(escapeRegExp(find), "g"), replace);
|
||||
}
|
Loading…
Reference in New Issue