Repository navigation
Expand file tree
/
Copy pathlocal_videos.en-us.html
More file actions
244 lines (219 loc) · 9.77 KB
/
Copy pathlocal_videos.en-us.html
File metadata and controls
244 lines (219 loc) · 9.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<!DOCTYPE html>
<html>
<head>
<title>Local Videos</title>
<script src="./download.js"></script>
<script src="./local_page.en-us.js"></script>
<link rel="StyleSheet" href="./local_page.css" type="text/css" />
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
</style>
<script src="./unpkg.com_hyperlist@1.0.0_dist_hyperlist.js"></script>
</head>
<body>
<div class="search-bar">
<input id="search-input" type="text" placeholder="Search videos..." oninput="onSearch()">
<div class="notification">
<p id="storage-notification">Used Storage: Unknown <br> This is a temporary storage space. Storing too many videos will cause the browser to crash. Please delete unnecessary videos in time. If you want to save it for a long time, please export the video file on the video playback page.</p>
<!-- <button id="compactBtn" onclick="compact()" class="button">compact</button> -->
</div>
</div>
<div style="display: none;" id="deletingPannel" class="fullscreen">
<p>Deleting, please wait</p>
<p id="deletingProgress"></p>
</div>
<div class="container"></div>
<script>
const language = 'en-us'
function timestampToFormattedDate(timestamp) {
const date = new Date(timestamp);
const year = date.getFullYear();
const month = ("0" + (date.getMonth() + 1)).slice(-2);
const day = ("0" + date.getDate()).slice(-2);
const hours = ("0" + date.getHours()).slice(-2);
const minutes = ("0" + date.getMinutes()).slice(-2);
const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}`;
return formattedDate;
}
const container = document.querySelector('.container');
var searchBar = document.querySelector('.search-bar');
var styles = window.getComputedStyle(searchBar);
var margin = parseFloat(styles['marginTop']) + parseFloat(styles['marginBottom']);
var searchBarHeight = searchBar.offsetHeight + margin;
let allM3u8Keys = [];
let data = allM3u8Keys;
let todayHistory = [];
function generateConfig(data) {
return config = {
height: window.innerHeight - searchBarHeight,
itemHeight: 500, // Approximate height of a tweet
total: data.length, // Total number of tweets
generate(index) {
let element = data[index];
// Generate a tweet.
const tweet = document.createElement('div');
tweet.classList.add('tweet');
tweet.innerHTML = `
<div class="images">
</div>
<div class="title">
<a id="titleLink" target="_blank" class="title-text"></a>
</div>
<div class="buttons">
<a id="playBtn" target="_blank" class="button">Play</a>
<a id="originalLink" target="_blank" class="button">Original website</a>
<button id="deleteBtn" class="button">Delete</button>
</div>
<div class="timestampfooter">
<p id="statusText" class="status-text status_${parseInt(element.status)}"><p>
<p id="timestamp" class="timestamp-text"></p>
</div>
`;
tweet.querySelector("#statusText").innerText = GetDownloadStatusStr(element.status)
tweet.querySelector("#timestamp").innerText = `Downloaded at: ${timestampToFormattedDate(element.saveTime)}`
tweet.querySelector('#titleLink').innerText = element.title;
tweet.querySelector('#titleLink').href = "./local_video_player.en-us.html#" + element.m3u8Url;
tweet.querySelector("#deleteBtn").onclick = () => {
deleteVideo(element.m3u8Url)
}
tweet.querySelector("#originalLink").href = element.pageUrl;
tweet.querySelector("#playBtn").href = "./local_video_player.en-us.html#" + element.m3u8Url;
container.appendChild(tweet);
var styles = window.getComputedStyle(tweet);
var margin = parseFloat(styles['marginTop']) + parseFloat(styles['marginBottom']);
var newHeight = tweet.offsetHeight + margin;
return { element: tweet, height: newHeight };
}
};
}
var list = undefined
// Initialize a new Hyperlist instance with the configuration
async function onSearch() {
if (allM3u8Keys.length == 0) {
await loadData()
}
let keywords = document.querySelector('#search-input').value;
const searchData = data.filter(x => x.title.indexOf(keywords) != -1);
list.refresh(container, generateConfig(searchData));
}
window.addEventListener('resize', onSearch)
setTimeout(() => {
loadData()
}, 500);
async function loadData() {
await new Promise(r => setTimeout(r, 500));
// TODO, chrome will compact leveldb for this request
// requestStorageEstimate();
allM3u8Keys = await regexMatchKeys('m3u8s', '.');
const tmpData = [];
for (let i in allM3u8Keys) {
const key = allM3u8Keys[i]
let m3u8Data = await readFromIndexedDB('m3u8s-mini', key);
tmpData.push(m3u8Data);
console.log(m3u8Data)
}
tmpData.sort((l, r) => r.saveTime - l.saveTime)
data = tmpData
list = new HyperList(container, generateConfig(data));
// cleanUselessVideos()
}
async function cleanUselessVideos() {
return; // don't use, has issue
m3u8Ids = []
data.forEach(m3u8 => {
try {
if (m3u8.m3u8Id) {
m3u8Ids.push(m3u8.m3u8Id)
}
} catch { }
})
console.log(m3u8Ids)
console.log(`(?<!${m3u8Ids.join('|')})$`)
uselessVideos = await regexMatchKeys('videos', `(?<!${m3u8Ids.join('|')})$`)
console.log(uselessVideos)
for (let i in uselessVideos) {
const videoKey = uselessVideos[i];
const m3u8Id = extractM3u8IdFromKey(videoKey);
const test = await regexMatchKeys('m3u8s', m3u8Id);
if (test.length == 0) {
// await deleteFromIndexedDB('videos', videoKey)
}
}
}
async function deleteVideo(m3u8Url) {
show(document.querySelector('#deletingPannel'))
let m3u8Data = undefined
for (let i in allM3u8Keys) {
const key = allM3u8Keys[i];
if (m3u8Url === key) {
m3u8Data = await readFromIndexedDB('m3u8s', key);
}
}
if (m3u8Data == undefined) {
return;
}
await updateM3u8Status(m3u8Url, 2)
let m3u8Head = "-m3u8Id-" + m3u8Data.m3u8Id + "-end-"
await iosDeleteByPrefix('videos' + m3u8Head)
await iosDeleteByPrefix('m3u8s' + m3u8Head)
await iosDeleteByPrefix('future' + m3u8Head)
let tsFilesIds = await regexMatchKeys('videos', "^" + m3u8Head);
console.log(tsFilesIds)
for (let i in tsFilesIds) {
const id = tsFilesIds[i];
if (!(await deleteFromIndexedDB('videos', id))) {
hide(document.querySelector('#deletingPannel'))
return;
}
document.querySelector("#deletingProgress").innerText = `${parseInt(i) + 1}/${tsFilesIds.length}`
}
let futureFilesIds = await regexMatchKeys('future', "^" + m3u8Head);
console.log(futureFilesIds)
for (let id of futureFilesIds) {
await deleteFromIndexedDB('future', id)
}
await deleteFromIndexedDB('m3u8s', m3u8Url);
data = data.filter(x => x.m3u8Url != m3u8Url);
onSearch()
hide(document.querySelector('#deletingPannel'))
compact();
}
function compact() {
window.postMessage({
source: "VideoTogether",
type: 3009,
data: {
beginKey: "",
endKey: "~"
}
}, '*')
}
async function debug(m3u8Url) {
let m3u8Data = undefined
for (let i in allM3u8Keys) {
const key = allM3u8Keys[i];
if (m3u8Url === key) {
m3u8Data = await readFromIndexedDB('m3u8s', key);
}
}
if (m3u8Data == undefined) {
return;
}
let tsFilesIds = await regexMatchKeys('videos', "^-m3u8Id-" + m3u8Data.m3u8Id + "-end-");
console.log(tsFilesIds)
}
window.addEventListener("message", e => {
if (e.data.source == "VideoTogether") {
switch (e.data.type) {
case 2010: {
document.querySelector("#storage-notification").innerText = `Used Storage: ${parseInt(e.data.data.data / 1024 / 1024)}MB`
break;
}
}
}
})
</script>
</body>
</html>