mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
Refactor SQLite to inform user of database errors
This commit is contained in:
@@ -44,26 +44,15 @@ namespace VRCX
|
|||||||
m_Connection.Close();
|
m_Connection.Close();
|
||||||
m_Connection.Dispose();
|
m_Connection.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ExecuteJson(string sql, IDictionary<string, object> args = null)
|
// for Electron
|
||||||
|
public string ExecuteJson(string sql, IDictionary<string, object>? args = null)
|
||||||
{
|
{
|
||||||
var result = Execute(sql, args);
|
var result = Execute(sql, args);
|
||||||
if (result.Item1 != null)
|
return JsonSerializer.Serialize(result);
|
||||||
{
|
|
||||||
return JsonSerializer.Serialize(new
|
|
||||||
{
|
|
||||||
status = "error",
|
|
||||||
message = result.Item1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return JsonSerializer.Serialize(new
|
|
||||||
{
|
|
||||||
status = "success",
|
|
||||||
data = result.Item2
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tuple<string, object[]> Execute(string sql, IDictionary<string, object> args = null)
|
public object[][] Execute(string sql, IDictionary<string, object>? args = null)
|
||||||
{
|
{
|
||||||
m_ConnectionLock.EnterReadLock();
|
m_ConnectionLock.EnterReadLock();
|
||||||
try
|
try
|
||||||
@@ -88,11 +77,7 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
result.Add(values);
|
result.Add(values);
|
||||||
}
|
}
|
||||||
return new Tuple<string, object[]>(null, result.ToArray());
|
return result.ToArray();
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new Tuple<string, object[]>(ex.Message, null);
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -100,9 +85,9 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ExecuteNonQuery(string sql, IDictionary<string, object> args = null)
|
public int ExecuteNonQuery(string sql, IDictionary<string, object>? args = null)
|
||||||
{
|
{
|
||||||
int result = -1;
|
var result = -1;
|
||||||
m_ConnectionLock.EnterWriteLock();
|
m_ConnectionLock.EnterWriteLock();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ namespace VRCX
|
|||||||
);
|
);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var item = (object[])values.Item2[0];
|
var item = values[0];
|
||||||
using var stream = new MemoryStream(Convert.FromBase64String((string)item[0]));
|
using var stream = new MemoryStream(Convert.FromBase64String((string)item[0]));
|
||||||
_cookieContainer = new CookieContainer();
|
_cookieContainer = new CookieContainer();
|
||||||
_cookieContainer.Add(System.Text.Json.JsonSerializer.Deserialize<CookieCollection>(stream));
|
_cookieContainer.Add(System.Text.Json.JsonSerializer.Deserialize<CookieCollection>(stream));
|
||||||
|
|||||||
@@ -957,7 +957,7 @@
|
|||||||
<div class="detail">
|
<div class="detail">
|
||||||
<span
|
<span
|
||||||
class="name"
|
class="name"
|
||||||
:style="{ color: user.user.$userColour }"
|
:style="{ color: user.user?.$userColour }"
|
||||||
v-text="user.user.displayName" />
|
v-text="user.user.displayName" />
|
||||||
<span class="extra">
|
<span class="extra">
|
||||||
<template v-if="hasGroupPermission(groupDialog.ref, 'group-members-manage')">
|
<template v-if="hasGroupPermission(groupDialog.ref, 'group-members-manage')">
|
||||||
@@ -1018,7 +1018,7 @@
|
|||||||
<div class="detail">
|
<div class="detail">
|
||||||
<span
|
<span
|
||||||
class="name"
|
class="name"
|
||||||
:style="{ color: user.user.$userColour }"
|
:style="{ color: user.user?.$userColour }"
|
||||||
v-text="user.user.displayName" />
|
v-text="user.user.displayName" />
|
||||||
<span class="extra">
|
<span class="extra">
|
||||||
<template v-if="hasGroupPermission(groupDialog.ref, 'group-members-manage')">
|
<template v-if="hasGroupPermission(groupDialog.ref, 'group-members-manage')">
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<el-button @click="cancelEditAndSendInvite">
|
<el-button @click="cancelEditAndSendInvite">
|
||||||
{{ t('dialog.edit_send_invite_message.cancel') }}
|
{{ t('dialog.edit_send_invite_message.cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" @click="saveEditAndSendInvite">
|
<el-button type="primary" @click="saveEditAndSendInvite" :disabled="!editAndSendInviteDialog.newMessage">
|
||||||
{{ t('dialog.edit_send_invite_message.send') }}
|
{{ t('dialog.edit_send_invite_message.send') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,35 +1,73 @@
|
|||||||
// requires binding of SQLite
|
import { ElMessageBox } from 'element-plus';
|
||||||
|
|
||||||
|
import { openExternalLink } from '../shared/utils';
|
||||||
|
|
||||||
|
// requires binding of SQLite
|
||||||
class SQLiteService {
|
class SQLiteService {
|
||||||
async execute(callback, sql, args = null) {
|
handleSQLiteError(e) {
|
||||||
if (LINUX) {
|
if (typeof e.message === 'string') {
|
||||||
if (args) {
|
if (e.message.includes('database disk image is malformed')) {
|
||||||
args = new Map(Object.entries(args));
|
ElMessageBox.confirm(
|
||||||
|
'Please repair or delete your database file by following these instructions.',
|
||||||
|
'Your database is corrupted',
|
||||||
|
{
|
||||||
|
confirmButtonText: 'Confirm',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(async (action) => {
|
||||||
|
if (action !== 'confirm') return;
|
||||||
|
openExternalLink(
|
||||||
|
'https://github.com/vrcx-team/VRCX/wiki#how-to-repair-vrcx-database'
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
var json = await SQLite.ExecuteJson(sql, args);
|
if (e.message.includes('database or disk is full')) {
|
||||||
var items = JSON.parse(json);
|
ElMessageBox.alert(
|
||||||
if (json.status === 'error') {
|
'Please free up some disk space.',
|
||||||
throw new Error(json.message);
|
'Disk containing database is full',
|
||||||
|
{
|
||||||
|
confirmButtonText: 'OK',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).catch(() => {});
|
||||||
}
|
}
|
||||||
items.data.forEach((item) => {
|
|
||||||
callback(item);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var item = await SQLite.Execute(sql, args);
|
throw e;
|
||||||
if (item.Item1 !== null) {
|
|
||||||
throw item.Item1;
|
|
||||||
}
|
|
||||||
item.Item2?.forEach((item) => {
|
|
||||||
callback(item);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
executeNonQuery(sql, args = null) {
|
async execute(callback, sql, args = null) {
|
||||||
if (LINUX && args) {
|
try {
|
||||||
args = new Map(Object.entries(args));
|
if (LINUX) {
|
||||||
|
if (args) {
|
||||||
|
args = new Map(Object.entries(args));
|
||||||
|
}
|
||||||
|
var json = await SQLite.ExecuteJson(sql, args);
|
||||||
|
var items = JSON.parse(json);
|
||||||
|
items.forEach((item) => {
|
||||||
|
callback(item);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var data = await SQLite.Execute(sql, args);
|
||||||
|
data.forEach((row) => {
|
||||||
|
callback(row);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
this.handleSQLiteError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeNonQuery(sql, args = null) {
|
||||||
|
try {
|
||||||
|
if (LINUX && args) {
|
||||||
|
args = new Map(Object.entries(args));
|
||||||
|
}
|
||||||
|
return await SQLite.ExecuteNonQuery(sql, args);
|
||||||
|
} catch (e) {
|
||||||
|
this.handleSQLiteError(e);
|
||||||
}
|
}
|
||||||
return SQLite.ExecuteNonQuery(sql, args);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
src/types/globals.d.ts
vendored
9
src/types/globals.d.ts
vendored
@@ -22,7 +22,7 @@ declare global {
|
|||||||
utils: any;
|
utils: any;
|
||||||
dayjs: any;
|
dayjs: any;
|
||||||
configRepository: any;
|
configRepository: any;
|
||||||
datebase: any;
|
database: any;
|
||||||
gameLogService: any;
|
gameLogService: any;
|
||||||
crypto: any;
|
crypto: any;
|
||||||
sqliteService: any;
|
sqliteService: any;
|
||||||
@@ -120,12 +120,9 @@ declare global {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const SQLite: {
|
const SQLite: {
|
||||||
Execute: (
|
Execute: (sql: string, args: string) => Promise<any[]>;
|
||||||
sql: string,
|
|
||||||
args: string
|
|
||||||
) => Promise<{ Item1: any; Item2: any[] }>;
|
|
||||||
ExecuteJson: (sql: string, args: string) => Promise<string>;
|
ExecuteJson: (sql: string, args: string) => Promise<string>;
|
||||||
ExecuteNonQuery: (sql: string, args: string) => Promise<void>;
|
ExecuteNonQuery: (sql: string, args: string) => Promise<Number>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const LogWatcher: {
|
const LogWatcher: {
|
||||||
|
|||||||
@@ -23,9 +23,12 @@
|
|||||||
<el-button @click="cancelEditAndSendInviteResponse">{{
|
<el-button @click="cancelEditAndSendInviteResponse">{{
|
||||||
t('dialog.edit_send_invite_response_message.cancel')
|
t('dialog.edit_send_invite_response_message.cancel')
|
||||||
}}</el-button>
|
}}</el-button>
|
||||||
<el-button type="primary" @click="saveEditAndSendInviteResponse">{{
|
<el-button
|
||||||
t('dialog.edit_send_invite_response_message.send')
|
type="primary"
|
||||||
}}</el-button>
|
@click="saveEditAndSendInviteResponse"
|
||||||
|
:disabled="!editAndSendInviteResponseDialog.newMessage"
|
||||||
|
>{{ t('dialog.edit_send_invite_response_message.send') }}</el-button
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user