shiori/view/index.html

692 lines
31 KiB
HTML
Raw Normal View History

2018-02-11 22:00:56 +08:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="/css/fontawesome.css">
<link rel="stylesheet" href="/css/source-sans-pro.css">
2018-05-18 15:07:15 +08:00
<link rel="stylesheet" href="/css/yla-dialog.css">
<link rel="stylesheet" href="/css/yla-tooltip.css">
<link rel="stylesheet" href="/css/stylesheet.css">
2018-02-11 22:00:56 +08:00
<script src="/js/vue.js"></script>
<script src="/js/axios.js"></script>
2018-02-22 17:48:36 +08:00
<script src="/js/js-cookie.js"></script>
2018-05-18 15:07:15 +08:00
<script src="/js/component/yla-tooltip.js"></script>
<script src="/js/component/yla-dialog.js"></script>
<script src="/js/page/base.js"></script>
2018-02-26 14:43:17 +08:00
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/res/apple-touch-icon-144x144.png" />
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="/res/apple-touch-icon-152x152.png" />
<link rel="icon" type="image/png" href="/res/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="/res/favicon-16x16.png" sizes="16x16" />
2018-02-11 22:00:56 +08:00
<title>Shiori - Bookmarks Manager</title>
</head>
<body>
2018-05-22 21:13:28 +08:00
<div id="index-page" class="page" :class="{night: nightMode}">
2018-05-18 15:07:15 +08:00
<div id="sidebar">
<p id="logo"></p>
<yla-tooltip placement="right" content="Reload data">
<a @click="reloadData" v-show="!editMode">
<i class="fas fa-sync-alt fa-fw" :class="loading && 'fa-spin'"></i>
</a>
</yla-tooltip>
<yla-tooltip placement="right" content="Add new bookmark">
2018-06-06 22:48:46 +08:00
<a :href="bookmarklet" @click="showDialogAdd" v-show="!editMode && !loading">
<span>+Shiori</span>
<i class="fas fa-plus fa-fw"></i>
</a>
</yla-tooltip>
<yla-tooltip placement="right" :content="editMode ? 'Cancel batch edit' : 'Batch edit'">
2018-05-24 13:39:36 +08:00
<a @click="toggleEditMode" v-show="!loading">
<i class="fas fa-fw" :class="editMode ? 'fa-times' : 'fa-pencil-alt'"></i>
2018-05-18 15:07:15 +08:00
</a>
</yla-tooltip>
2018-05-24 13:39:36 +08:00
<yla-tooltip placement="right" content="Show tags">
<a @click="showDialogTags" v-show="!editMode && !loading">
<i class="fas fa-fw fa-tags"></i>
</a>
</yla-tooltip>
2018-05-18 15:07:15 +08:00
<div class="spacer"></div>
2018-05-21 17:37:48 +08:00
<yla-tooltip placement="right" :content="listView ? 'Switch to grid view' : 'Switch to list view'">
<a @click="toggleListView">
<i class="fas fa-fw" :class="listView ? 'fa-th-large' : 'fa-th-list'"></i>
</a>
</yla-tooltip>
2018-05-18 15:07:15 +08:00
<yla-tooltip placement="right" content="Toggle night mode">
2018-05-21 21:26:18 +08:00
<a @click="toggleNightMode">
2018-05-22 21:13:28 +08:00
<i class="fas fa-fw" :class="nightMode ? 'fa-sun' : 'fa-moon'"></i>
2018-05-18 15:07:15 +08:00
</a>
</yla-tooltip>
<yla-tooltip placement="right" content="Log out">
2018-05-23 21:14:26 +08:00
<a @click="showDialogLogout">
2018-05-18 15:07:15 +08:00
<i class="fas fa-sign-out-alt fa-fw"></i>
</a>
</yla-tooltip>
2018-02-11 22:00:56 +08:00
</div>
2018-05-18 15:07:15 +08:00
<div id="body">
2018-05-22 23:35:16 +08:00
<div id="header" class="header" v-if="!editMode">
2018-05-21 15:03:08 +08:00
<input type="text" v-model.trim="search" placeholder="Search bookmarks by url, tags, title or content" @focus="$event.target.select()" @keyup.enter="loadData">
<a title="Search" @click="loadData">
2018-05-18 15:07:15 +08:00
<i class="fas fa-search fa-fw"></i>
</a>
2018-02-14 12:41:43 +08:00
</div>
2018-05-22 23:35:16 +08:00
<div id="batch-edit" class="header" v-if="editMode">
<p>{{selected.length}} Items selected</p>
<a :class="{disabled: selected.length === 0}" @click="showDialogDelete(selected)">
<i class="fas fa-fw fa-trash-alt"></i>
2018-05-24 00:12:16 +08:00
<span>Delete</span>
2018-05-22 23:35:16 +08:00
</a>
<a :class="{disabled: selected.length === 0}" @click="showDialogAddTags(selected)">
2018-05-22 23:35:16 +08:00
<i class="fas fa-fw fa-tags"></i>
2018-05-24 00:12:16 +08:00
<span>Add tags</span>
2018-05-22 23:35:16 +08:00
</a>
<a :class="{disabled: selected.length === 0}" @click="showDialogUpdateCache(selected)">
<i class="fas fa-fw fa-cloud-download-alt"></i>
2018-05-24 00:12:16 +08:00
<span>Update cache</span>
2018-05-22 23:35:16 +08:00
</a>
<a id="cancel-edit" @click="toggleEditMode">
<i class="fas fa-fw fa-times"></i>
</a>
</div>
2018-05-24 13:58:56 +08:00
<div id="grid" :class="{list: listView}">
<div class="pagination-box" v-if="maxPage > 0">
<p>Page</p>
<input type="text" placeholder="1" :value="page+1" @focus="$event.target.select()" @keyup.enter="changePage($event.target.value-1)" :disabled="editMode">
<p>{{maxPage+1}}</p>
<div class="spacer"></div>
<template v-if="!editMode">
<a v-if="page > 1" title="Go to first page" @click="changePage(0)">
<i class="fas fa-fw fa-angle-double-left"></i>
</a>
<a v-if="page > 0" title="Go to previous page" @click="changePage(page-1)">
<i class="fa fa-fw fa-angle-left"></i>
</a>
<a v-if="page < maxPage" title="Go to next page" @click="changePage(page+1)">
<i class="fa fa-fw fa-angle-right"></i>
</a>
<a v-if="page < maxPage - 1" title="Go to last page" @click="changePage(maxPage)">
<i class="fas fa-fw fa-angle-double-right"></i>
2018-05-21 17:37:48 +08:00
</a>
2018-05-24 13:58:56 +08:00
</template>
</div>
<div class="bookmark" v-for="(book, idx) in visibleBookmarks" :class="{selected: isSelected(idx)}">
<a class="bookmark-selector" v-if="editMode" @click="toggleSelection(idx)"></a>
<a class="bookmark-link" :href="book.hasContent ? '/bookmark/'+book.id : null" :title="book.hasContent ? 'View cache' : null" target="_blank">
<img v-if="book.imageURL !== ''" :src="book.imageURL">
<p class="title">{{book.title}}</p>
<p class="excerpt" v-if="book.imageURL === ''">{{book.excerpt}}</p>
</a>
<div class="bookmark-tags" v-if="book.tags.length > 0">
<a v-for="tag in book.tags" @click="filterTag(tag.name)">{{tag.name}}</a>
2018-05-21 17:37:48 +08:00
</div>
2018-05-24 13:58:56 +08:00
<div class="spacer"></div>
<div class="bookmark-menu">
<a class="url" title="View original" :href="book.url" target="_blank">
{{getHostname(book.url)}}
</a>
<a title="Edit bookmark" @click="showDialogEdit(idx)">
<i class="fas fa-pencil-alt"></i>
</a>
<a title="Delete bookmark" @click="showDialogDelete([idx])">
<i class="fas fa-trash-alt"></i>
</a>
<a title="Update cache" @click="showDialogUpdateCache([idx])">
<i class="fas fa-cloud-download-alt"></i>
</a>
2018-05-21 17:37:48 +08:00
</div>
2018-03-10 11:39:38 +08:00
</div>
2018-05-24 13:58:56 +08:00
<div class="pagination-box" v-if="maxPage > 0">
<p>Page</p>
<input type="text" placeholder="1" :value="page+1" @focus="$event.target.select()" @keyup.enter="changePage($event.target.value-1)" :disabled="editMode">
<p>{{maxPage+1}}</p>
<div class="spacer"></div>
<template v-if="!editMode">
<a v-if="page > 1" title="Go to first page" @click="changePage(0)">
<i class="fas fa-fw fa-angle-double-left"></i>
</a>
<a v-if="page > 0" title="Go to previous page" @click="changePage(page-1)">
<i class="fa fa-fw fa-angle-left"></i>
</a>
<a v-if="page < maxPage" title="Go to next page" @click="changePage(page+1)">
<i class="fa fa-fw fa-angle-right"></i>
</a>
<a v-if="page < maxPage - 1" title="Go to last page" @click="changePage(maxPage)">
<i class="fas fa-fw fa-angle-double-right"></i>
</a>
</template>
</div>
<div id="grid-padding"></div>
2018-03-10 11:39:38 +08:00
</div>
</div>
2018-05-24 13:39:36 +08:00
<yla-dialog id="dialog-tags" v-bind="dialogTags">
<a v-for="tag in tags" @click="filterTag(tag.name)">
<span>{{tag.name}}</span>
<span>{{tag.nBookmarks}}</span>
</a>
</yla-dialog>
2018-05-18 15:07:15 +08:00
<yla-dialog v-bind="dialog"></yla-dialog>
2018-02-11 22:00:56 +08:00
</div>
<script>
2018-05-21 14:28:08 +08:00
// Define global variable
var pageSize = 30;
2018-05-18 15:07:15 +08:00
// Prepare axios instance
2018-02-22 17:48:36 +08:00
var token = Cookies.get('token'),
2018-05-18 15:07:15 +08:00
rest = axios.create();
2018-02-22 17:48:36 +08:00
2018-05-18 17:18:38 +08:00
rest.defaults.timeout = 60000;
2018-05-18 15:07:15 +08:00
rest.defaults.headers.common['Authorization'] = 'Bearer ' + token;
2018-02-11 22:00:56 +08:00
2018-05-18 15:07:15 +08:00
// Register Vue component
Vue.component('yla-dialog', new YlaDialog());
Vue.component('yla-tooltip', new YlaTooltip());
new Vue({
el: '#index-page',
mixins: [new Base()],
2018-05-24 13:39:36 +08:00
data() {
return {
loading: false,
tags: [],
bookmarks: [],
search: '',
page: 0,
maxPage: 0,
listView: false,
nightMode: false,
editMode: false,
selected: [],
2018-06-06 22:48:46 +08:00
bookmarklet: '',
2018-05-24 13:39:36 +08:00
dialogTags: {
visible: false,
loading: false,
title: 'Existing Tags',
mainText: 'Cancel',
mainClick: () => {
this.dialogTags.visible = false;
},
}
}
2018-05-21 14:28:08 +08:00
},
computed: {
visibleBookmarks() {
var start = this.page * pageSize,
finish = start + pageSize;
return this.bookmarks.slice(start, finish);
}
2018-02-11 22:00:56 +08:00
},
methods: {
2018-05-18 15:07:15 +08:00
loadData() {
2018-02-24 15:01:52 +08:00
if (this.loading) return;
2018-05-21 15:03:08 +08:00
// Parse search query
2018-05-24 22:53:34 +08:00
var rxTagA = /['"]#([^'"]+)['"]/g,
rxTagB = /(^|\s+)#(\S+)/g,
keyword = this.search,
2018-05-21 15:03:08 +08:00
tags = [];
2018-05-24 22:53:34 +08:00
// Fetch tag A first
while ((result = rxTagA.exec(keyword)) !== null) {
tags.push(result[1]);
}
// Clear tag A from keyword
keyword = keyword.replace(rxTagA, '');
// Fetch tag B
while ((result = rxTagB.exec(keyword)) !== null) {
2018-05-21 15:03:08 +08:00
tags.push(result[2]);
}
2018-05-24 22:53:34 +08:00
// Clear tag B from keyword and clean it
keyword = keyword.replace(rxTagB, '').trim().replace(/\s+/g, ' ');
2018-02-23 15:30:58 +08:00
// Fetch data
2018-02-12 22:06:53 +08:00
this.loading = true;
2018-05-21 15:03:08 +08:00
rest.get('/api/bookmarks', {
params: {
keyword: keyword,
2018-05-24 22:53:34 +08:00
tags: tags.join(',')
2018-05-21 15:03:08 +08:00
}
})
2018-05-18 15:07:15 +08:00
.then((response) => {
this.loading = false;
this.bookmarks = response.data;
2018-05-21 14:28:08 +08:00
this.page = 0;
this.maxPage = Math.ceil(this.bookmarks.length / pageSize) - 1;
2018-05-24 00:12:16 +08:00
window.scrollTo(0, 0);
2018-02-12 22:06:53 +08:00
})
2018-05-18 15:07:15 +08:00
.catch((error) => {
var errorMsg = (error.response ? error.response.data : error.message).trim();
this.loading = false;
this.showErrorDialog(errorMsg);
2018-02-14 12:41:43 +08:00
});
},
2018-05-21 17:37:48 +08:00
reloadData() {
if (this.loading) return;
this.search = '';
this.loadData();
},
2018-05-21 14:28:08 +08:00
changePage(target) {
target = parseInt(target, 10) || 0;
if (target >= this.maxPage) this.page = this.maxPage;
else if (target <= 0) this.page = 0;
else this.page = target;
2018-05-24 00:12:16 +08:00
window.scrollTo(0, 0);
2018-05-21 17:37:48 +08:00
},
toggleListView() {
this.listView = !this.listView;
2018-05-24 00:12:16 +08:00
window.scrollTo(0, 0);
2018-05-21 17:37:48 +08:00
localStorage.setItem('shiori-list-view', this.listView ? '1' : '0');
2018-05-21 14:28:08 +08:00
},
2018-05-21 21:26:18 +08:00
toggleNightMode() {
this.nightMode = !this.nightMode;
localStorage.setItem('shiori-night-mode', this.nightMode ? '1' : '0');
},
2018-05-22 23:35:16 +08:00
toggleEditMode() {
this.editMode = !this.editMode;
this.selected = [];
},
toggleSelection(idx) {
var pos = this.selected.indexOf(idx);
if (pos === -1) this.selected.push(idx);
else this.selected.splice(pos, 1);
},
isSelected(idx) {
return this.selected.indexOf(idx) > -1;
},
filterTag(tag) {
2018-05-24 22:53:34 +08:00
// Prepare variable
var rxSpace = /\s+/g,
searchTag = rxSpace.test(tag) ? '"#' + tag + '"' : '#' + tag;
// Check if tag already exist in search
2018-05-24 22:53:34 +08:00
rxTag = new RegExp(searchTag, 'g');
if (rxTag.test(this.search)) return;
// Create new search query
var newSearch = this.search
.replace(rxTag, '')
2018-05-24 22:53:34 +08:00
.replace(rxSpace, ' ')
.trim();
// Load data
2018-05-24 22:53:34 +08:00
this.search = (newSearch + ' ' + searchTag).trim();
2018-05-24 13:39:36 +08:00
this.dialogTags.visible = false;
this.loadData();
},
2018-06-06 22:48:46 +08:00
showDialogAdd(e) {
e.preventDefault();
2018-05-18 15:07:15 +08:00
this.showDialog({
title: 'New Bookmark',
2018-05-19 14:36:51 +08:00
content: 'Create a new bookmark',
2018-05-18 15:07:15 +08:00
fields: [{
name: 'url',
2018-05-19 14:36:51 +08:00
label: 'Url, start with http://...',
}, {
name: 'title',
label: 'Custom title (optional)'
}, {
name: 'excerpt',
label: 'Custom excerpt (optional)',
type: 'area'
}, {
name: 'tags',
2018-05-24 22:53:34 +08:00
label: 'Comma separated tags (optional)'
}, ],
2018-05-18 15:07:15 +08:00
mainText: 'OK',
secondText: 'Cancel',
mainClick: (data) => {
2018-05-19 14:36:51 +08:00
// Prepare tags
var tags = data.tags
.toLowerCase()
2018-05-24 22:53:34 +08:00
.replace(/\s+/g, ' ')
.split(/\s*,\s*/g)
.filter(tag => tag !== '')
.map(tag => {
2018-05-19 14:36:51 +08:00
return {
name: tag
};
});
// Send data
2018-05-18 15:07:15 +08:00
this.dialog.loading = true;
rest.post('/api/bookmarks', {
2018-05-19 14:36:51 +08:00
url: data.url.trim(),
title: data.title.trim(),
excerpt: data.excerpt.trim(),
tags: tags
})
.then((response) => {
this.dialog.loading = false;
this.dialog.visible = false;
this.bookmarks.splice(0, 0, response.data);
})
.catch((error) => {
var errorMsg = (error.response ? error.response.data : error.message).trim();
this.showErrorDialog(errorMsg);
});
}
});
},
2018-05-19 16:28:17 +08:00
showDialogEdit(idx) {
2018-05-28 16:54:59 +08:00
idx += this.page * pageSize;
2018-05-19 16:28:17 +08:00
var book = JSON.parse(JSON.stringify(this.bookmarks[idx])),
2018-05-26 17:44:53 +08:00
strTags = book.tags.map(tag => tag.name).join(', ');
2018-05-19 16:28:17 +08:00
this.showDialog({
title: 'Edit Bookmark',
content: 'Edit the bookmark\'s data',
showLabel: true,
fields: [{
name: 'title',
label: 'Title',
value: book.title,
}, {
name: 'excerpt',
label: 'Excerpt',
type: 'area',
value: book.excerpt,
2018-05-19 17:11:18 +08:00
}, {
name: 'tags',
label: 'Tags',
value: strTags,
2018-05-19 16:28:17 +08:00
}],
mainText: 'OK',
secondText: 'Cancel',
mainClick: (data) => {
// Validate input
if (data.title.trim() === '') return;
// Prepare tags
var tags = data.tags
.toLowerCase()
2018-05-24 22:53:34 +08:00
.replace(/\s+/g, ' ')
.split(/\s*,\s*/g)
.filter(tag => tag !== '')
.map(tag => {
2018-05-19 16:28:17 +08:00
return {
name: tag
};
});
// Set new data
book.title = data.title.trim();
book.excerpt = data.excerpt.trim();
book.tags = tags;
// Send data
this.dialog.loading = true;
rest.put('/api/bookmarks', book)
.then((response) => {
this.dialog.loading = false;
this.dialog.visible = false;
this.bookmarks.splice(idx, 1, response.data);
})
.catch((error) => {
var errorMsg = (error.response ? error.response.data : error.message).trim();
this.showErrorDialog(errorMsg);
});
}
});
},
2018-05-19 14:36:51 +08:00
showDialogDelete(indices) {
// Check and prepare indices
if (!(indices instanceof Array)) return;
if (indices.length === 0) return;
indices.sort();
2018-05-28 16:54:59 +08:00
// Set real indices value
indices = indices.map(item => item + this.page * pageSize)
// Create title and content
2018-05-19 14:36:51 +08:00
var title = "Delete Bookmarks",
content = "Delete the selected bookmarks ? This action is irreversible.";
if (indices.length === 1) {
title = "Delete Bookmark";
content = "Are you sure ? This action is irreversible.";
}
// Get list of bookmark ID
var listID = [];
for (var i = 0; i < indices.length; i++) {
2018-05-19 23:43:15 +08:00
listID.push(this.bookmarks[indices[i]].id);
2018-05-19 14:36:51 +08:00
}
// Show dialog
this.showDialog({
title: title,
content: content,
mainText: 'Yes',
secondText: 'No',
mainClick: () => {
this.dialog.loading = true;
rest.delete('/api/bookmarks/', {
data: listID
})
2018-05-18 15:07:15 +08:00
.then((response) => {
2018-05-22 23:35:16 +08:00
this.selected = [];
this.editMode = false;
2018-05-18 15:07:15 +08:00
this.dialog.loading = false;
this.dialog.visible = false;
2018-05-19 14:36:51 +08:00
for (var i = indices.length - 1; i >= 0; i--) {
this.bookmarks.splice(indices[i], 1);
}
})
2018-05-18 15:07:15 +08:00
.catch((error) => {
var errorMsg = (error.response ? error.response.data : error.message).trim();
this.showErrorDialog(errorMsg);
});
2018-05-18 15:07:15 +08:00
}
2018-02-13 17:14:08 +08:00
});
2018-05-18 15:07:15 +08:00
},
2018-05-19 17:11:18 +08:00
showDialogUpdateCache(indices) {
// Check and prepare indices
if (!(indices instanceof Array)) return;
if (indices.length === 0) return;
indices.sort();
2018-05-28 16:54:59 +08:00
// Set real indices value
indices = indices.map(item => item + this.page * pageSize)
2018-05-19 17:11:18 +08:00
// Get list of bookmark ID
var listID = [];
for (var i = 0; i < indices.length; i++) {
2018-05-19 23:43:15 +08:00
listID.push(this.bookmarks[indices[i]].id);
2018-05-19 17:11:18 +08:00
}
// Show dialog
this.showDialog({
title: 'Update Cache',
content: 'Update cache for selected bookmarks ? This action is irreversible.',
mainText: 'Yes',
secondText: 'No',
mainClick: () => {
this.dialog.loading = true;
rest.put('/api/cache/', listID)
.then((response) => {
2018-05-22 23:35:16 +08:00
this.selected = [];
this.editMode = false;
2018-05-19 17:11:18 +08:00
this.dialog.loading = false;
this.dialog.visible = false;
response.data.forEach(book => {
for (var i = 0; i < indices.length; i++) {
var idx = indices[i];
if (book.id === this.bookmarks[idx].id) {
this.bookmarks.splice(idx, 1, book);
break;
}
}
});
})
.catch((error) => {
var errorMsg = (error.response ? error.response.data : error.message).trim();
this.showErrorDialog(errorMsg);
});
}
});
},
showDialogAddTags(indices) {
// Check and prepare indices
if (!(indices instanceof Array)) return;
if (indices.length === 0) return;
indices.sort();
2018-05-28 16:54:59 +08:00
// Set real indices value
indices = indices.map(item => item + this.page * pageSize)
// Get list of bookmark ID
var listID = [];
for (var i = 0; i < indices.length; i++) {
listID.push(this.bookmarks[indices[i]].id);
}
this.showDialog({
title: 'Add New Tags',
content: 'Add new tags to selected bookmarks',
fields: [{
name: 'tags',
2018-05-24 22:53:34 +08:00
label: 'Comma separated tags',
value: '',
}],
mainText: 'OK',
secondText: 'Cancel',
mainClick: (data) => {
// Validate input
var tags = data.tags
.toLowerCase()
2018-05-24 22:53:34 +08:00
.replace(/\s+/g, ' ')
.split(/\s*,\s*/g)
.filter(tag => tag !== '')
.map(tag => {
return {
name: tag
};
});
if (tags.length === 0) return;
// Send data
this.dialog.loading = true;
rest.put('/api/bookmarks/tags', {
ids: listID,
tags: tags,
})
.then((response) => {
this.selected = [];
this.editMode = false;
this.dialog.loading = false;
this.dialog.visible = false;
response.data.forEach(book => {
for (var i = 0; i < indices.length; i++) {
var idx = indices[i];
if (book.id === this.bookmarks[idx].id) {
this.bookmarks.splice(idx, 1, book);
break;
}
}
});
})
2018-05-19 17:11:18 +08:00
.catch((error) => {
var errorMsg = (error.response ? error.response.data : error.message).trim();
this.showErrorDialog(errorMsg);
});
}
});
},
2018-05-24 13:39:36 +08:00
showDialogTags() {
this.dialogTags.visible = true;
this.dialogTags.loading = true;
rest.get('/api/tags', {
timeout: 5000
})
.then((response) => {
this.tags = response.data;
this.dialogTags.loading = false;
})
.catch((error) => {
var errorMsg = (error.response ? error.response.data : error.message).trim();
this.dialogTags.loading = false;
this.dialogTags.visible = false;
this.showErrorDialog(errorMsg);
});
},
2018-05-23 21:14:26 +08:00
showDialogLogout() {
this.showDialog({
title: 'Log Out',
content: 'Do you want to log out from shiori ?',
mainText: 'Yes',
secondText: 'No',
mainClick: () => {
Cookies.remove('token');
location.href = '/login';
}
});
},
2018-05-18 15:07:15 +08:00
getHostname(url) {
parser = document.createElement('a');
parser.href = url;
2018-05-19 14:36:51 +08:00
return parser.hostname.replace(/^www\./g, '');
2018-02-13 17:14:08 +08:00
}
},
2018-05-18 15:07:15 +08:00
mounted() {
2018-05-21 17:37:48 +08:00
// Read config from local storage
var listView = localStorage.getItem('shiori-list-view'),
nightMode = localStorage.getItem('shiori-night-mode');
this.listView = listView === '1';
this.nightMode = nightMode === '1';
2018-06-06 22:48:46 +08:00
// Create bookmarklet
var shioriURL = location.href.replace(/\/+$/g, ''),
baseBookmarklet = `(function () {
var shioriURL = '$SHIORI_URL',
bookmarkURL = location.href,
submitURL = shioriURL + '/submit?url=' + encodeURIComponent(bookmarkURL);
if (bookmarkURL.startsWith('https://') && !shioriURL.startsWith('https://')) {
window.open(submitURL, '_blank');
return;
}
var i = document.createElement('iframe');
i.src = submitURL;
i.frameBorder = '0';
i.allowTransparency = true;
i.style.position = 'fixed';
i.style.top = 0;
i.style.left = 0;
i.style.width = '100%';
i.style.height = '100%';
i.style.zIndex = 99999;
document.body.appendChild(i);
window.addEventListener('message', function onMessage(e) {
if (e.origin !== shioriURL) return;
if (e.data !== 'finished') return;
window.removeEventListener('message', onMessage);
document.body.removeChild(i);
});
}())`;
this.bookmarklet = 'javascript:' + baseBookmarklet
.replace('$SHIORI_URL', shioriURL)
.replace(/\s+/gm, ' ');
2018-05-21 17:37:48 +08:00
// Load data
2018-02-11 22:00:56 +08:00
this.loadData();
}
2018-05-18 15:07:15 +08:00
});
2018-02-11 22:00:56 +08:00
</script>
</body>
2018-03-10 11:39:38 +08:00
</html>