github.com/soulteary/pocket-bookcase@v0.0.0-20240428065142-0b5a9a0fc98a/internal/view/index.html (about)

     1  <!DOCTYPE html>
     2  <html lang="en">
     3  
     4  <head>
     5  	<base href="$$.RootPath$$">
     6  	<title>Shiori - Bookmarks Manager</title>
     7  
     8  	<meta charset="UTF-8">
     9  	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    10  
    11  	<link rel="apple-touch-icon-precomposed" sizes="152x152" href="assets/res/apple-touch-icon-152x152.png">
    12  	<link rel="apple-touch-icon-precomposed" sizes="144x144" href="assets/res/apple-touch-icon-144x144.png">
    13  	<link rel="icon" type="image/png" href="assets/res/favicon-32x32.png" sizes="32x32">
    14  	<link rel="icon" type="image/png" href="assets/res/favicon-16x16.png" sizes="16x16">
    15  	<link rel="icon" type="image/x-icon" href="assets/res/favicon.ico">
    16  
    17  	<link href="assets/css/style.css" rel="stylesheet">
    18  
    19  	<script src="assets/js/vue.min.js"></script>
    20  	<script src="assets/js/url.min.js"></script>
    21  </head>
    22  
    23  <body class="night">
    24  	<div id="main-scene" :class="{night: appOptions.NightMode}">
    25  		<div id="main-sidebar">
    26  			<a v-for="item in sidebarItems" :title="item.title" :class="{active: activePage === item.page}" @click="switchPage(item.page)">
    27  				<i class="fas fa-fw" :class="item.icon"></i>
    28  			</a>
    29  			<div class="spacer"></div>
    30  			<a title="Logout" @click="logout">
    31  				<i class="fas fa-fw fa-sign-out-alt"></i>
    32  			</a>
    33  		</div>
    34  		<keep-alive>
    35  			<component :is="activePage" :active-account="activeAccount" :app-options="appOptions" @setting-changed="saveSetting"></component>
    36  		</keep-alive>
    37  		<custom-dialog v-bind="dialog" />
    38  	</div>
    39  
    40  	<script type="module">
    41  		import basePage from "./assets/js/page/base.js";
    42  		import pageHome from "./assets/js/page/home.js";
    43  		import pageSetting from "./assets/js/page/setting.js";
    44  		import customDialog from "./assets/js/component/dialog.js";
    45  
    46  		var app = new Vue({
    47  			el: '#main-scene',
    48  			mixins: [basePage],
    49  			components: {
    50  				pageHome,
    51  				pageSetting,
    52  				customDialog
    53  			},
    54  			data: {
    55  				activePage: "page-home",
    56  				sidebarItems: [{
    57  					title: "Home",
    58  					icon: "fa-home",
    59  					page: "page-home",
    60  				}, {
    61  					title: "Setting",
    62  					icon: "fa-cog",
    63  					page: "page-setting",
    64  				}],
    65  			},
    66  			methods: {
    67  				switchPage(page) {
    68  					var pageName = page.replace("page-", ""),
    69  						state = { activePage: page },
    70  						url = new Url;
    71  
    72  					url.hash = pageName;
    73  					this.activePage = page;
    74  					history.pushState(state, page, url);
    75  				},
    76  				logout() {
    77  					this.showDialog({
    78  						title: "Log Out",
    79  						content: "Are you sure you want to log out ?",
    80  						mainText: "Yes",
    81  						secondText: "No",
    82  						mainClick: () => {
    83  							this.dialog.loading = true;
    84  							fetch(new URL("api/logout", document.baseURI), {
    85  								method: "post"
    86  							}).then(response => {
    87  								if (!response.ok) throw response;
    88  								return response;
    89  							}).then(() => {
    90  								localStorage.removeItem("shiori-account");
    91  								localStorage.removeItem("shiori-token");
    92  								document.cookie = `session-id=; Path=${new URL(document.baseURI).pathname}; Expires=Thu, 01 Jan 1970 00:00:00 GMT;`;
    93  								location.href = new URL("login", document.baseURI);
    94  							}).catch(err => {
    95  								this.dialog.loading = false;
    96  								this.getErrorMessage(err).then(msg => {
    97  									this.showErrorDialog(msg);
    98  								})
    99  							});
   100  						}
   101  					});
   102  				},
   103  				saveSetting(opts) {
   104  					this.appOptions = opts;
   105  					document.body.className = opts.config.NightMode ? "night" : "";
   106  				},
   107  				loadSetting() {
   108  					var opts = JSON.parse(localStorage.getItem("shiori-account")) || {},
   109  						ShowId = (typeof opts.config.ShowId === "boolean") ? opts.config.ShowId : false,
   110  						ListMode = (typeof opts.config.ListMode === "boolean") ? opts.config.ListMode : false,
   111  						HideThumbnail = (typeof opts.config.HideThumbnail === "boolean") ? opts.config.HideThumbnail : false,
   112  						HideExcerpt = (typeof opts.config.HideExcerpt === "boolean") ? opts.config.HideExcerpt : false,
   113  						NightMode = (typeof opts.config.NightMode === "boolean") ? opts.config.NightMode : false,
   114  						KeepMetadata = (typeof opts.config.KeepMetadata === "boolean") ? opts.config.KeepMetadata : false,
   115  						UseArchive = (typeof opts.config.UseArchive === "boolean") ? opts.config.UseArchive : false,
   116  						CreateEbook = (typeof opts.config.CreateEbook === "boolean") ? opts.config.CreateEbook : false,
   117  						MakePublic = (typeof opts.config.MakePublic === "boolean") ? opts.config.MakePublic : false;
   118  
   119  					this.appOptions = {
   120  						ShowId: ShowId,
   121  						ListMode: ListMode,
   122  						HideThumbnail: HideThumbnail,
   123  						HideExcerpt: HideExcerpt,
   124  						NightMode: NightMode,
   125  						KeepMetadata: KeepMetadata,
   126  						UseArchive: UseArchive,
   127  						CreateEbook: CreateEbook,
   128  						MakePublic: MakePublic,
   129  					};
   130  
   131  					document.body.className = NightMode ? "night" : "";
   132  				},
   133  				loadAccount() {
   134  					var account = JSON.parse(localStorage.getItem("shiori-account")) || {},
   135  						id = (typeof account.id === "number") ? account.id : 0,
   136  						username = (typeof account.username === "string") ? account.username : "",
   137  						owner = (typeof account.owner === "boolean") ? account.owner : false;
   138  
   139  					this.activeAccount = {
   140  						id: id,
   141  						username: username,
   142  						owner: owner,
   143  					};
   144  				}
   145  			},
   146  			mounted() {
   147  				// Load setting
   148  				this.loadSetting();
   149  				this.loadAccount();
   150  
   151  				// Prepare history state watcher
   152  				var stateWatcher = (e) => {
   153  					var state = e.state || {};
   154  					this.activePage = state.activePage || "page-home";
   155  				}
   156  
   157  				window.addEventListener('popstate', stateWatcher);
   158  				this.$once('hook:beforeDestroy', function () {
   159  					window.removeEventListener('popstate', stateWatcher);
   160  				})
   161  
   162  				// Set initial active page
   163  				var initialPage = (new Url).hash || "home";
   164  				if (initialPage === "home" || initialPage === "setting") {
   165  					this.activePage = `page-${initialPage}`;
   166  				} else {
   167  					history.replaceState(null, "page-home", "/#home");
   168  				}
   169  			}
   170  		})
   171  	</script>
   172  </body>
   173  
   174  </html>