mirror of
https://github.com/weyne85/chaturbate-dvr.git
synced 2025-10-29 16:58:56 +00:00
Updates and refactors
Channel_file.go - fix issue with segments not correctly ending when they were supposed to Log_type.go - moved log type to it's own file, setup global logging (touches on issue #47) Main.go - added update_log_level handler, setting global log level Channel.go, channel_internal.go, channel_util.go - updated to use new log_type Manager.go - updated to use new log_type, update from .com to .global (issue #74) Channel_update.go, create_channel.go, delete_channel.go, get_channel.go, get_settings.go, listen_update.go, pause_channel.go, resume_channel.go, terminal_program.go - go fmt / go vet Chaturbate_channels.json.sample - added sample json of the channels file, for mapping in docker config List_channels.go - refactored to sort by online status, so online is always at the first ones you see Script.js - adjust default settings, added pagination, added global log logic Index.html - updated to use online version of tocas ui, added pagination, added global log logic, visual improvements Removal of local tocas folder since using online version
This commit is contained in:
@@ -1,391 +1,410 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="is-secondary">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="/static/tocas/tocas.min.css" />
|
||||
<script src="/static/tocas/tocas.min.js"></script>
|
||||
<script src="/static/script.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;500;700&display=swap" rel="stylesheet" />
|
||||
<script src="https://unpkg.com/alpinejs" defer></script>
|
||||
<title>Chaturbate DVR</title>
|
||||
</head>
|
||||
<body x-data="data()">
|
||||
<!-- Create Dialog -->
|
||||
<dialog id="create-dialog" class="ts-modal is-large" data-clickaway="close">
|
||||
<div class="content">
|
||||
<!-- Header -->
|
||||
<div class="ts-content is-horizontally-padded is-secondary">
|
||||
<div class="ts-grid">
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-header">Add Channel</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<button class="ts-close is-rounded is-large is-secondary" x-on:click="closeCreateDialog"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Header -->
|
||||
|
||||
<div class="ts-divider"></div>
|
||||
|
||||
<!-- Form -->
|
||||
<div class="ts-content is-vertically-padded">
|
||||
<!-- Field: Channel Username -->
|
||||
<div class="ts-control is-wide">
|
||||
<div class="label">Channel Username</div>
|
||||
<div class="content">
|
||||
<div class="ts-input is-start-labeled">
|
||||
<div class="label">chaturbate.com/</div>
|
||||
<input type="text" autofocus x-model="form_data.username" />
|
||||
</div>
|
||||
<div class="ts-text is-description has-top-spaced-small">Use commas to separate multiple channel names. For example, "channel1,channel2,channel3".</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Channel Username -->
|
||||
|
||||
<!-- Field: Resolution -->
|
||||
<div class="ts-control is-wide has-top-spaced-large">
|
||||
<div class="label">Resolution</div>
|
||||
<div class="content">
|
||||
<div class="ts-grid">
|
||||
<div class="column">
|
||||
<div class="ts-select">
|
||||
<select x-model="form_data.resolution">
|
||||
<option value="2160">4K</option>
|
||||
<option value="1440">2K</option>
|
||||
<option value="1080">1080p</option>
|
||||
<option value="720">720p</option>
|
||||
<option value="540">540p</option>
|
||||
<option value="480">480p</option>
|
||||
<option value="240">240p</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="ts-select">
|
||||
<select x-model="form_data.resolution_fallback">
|
||||
<option value="up">or higher</option>
|
||||
<option value="down">or lower</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ts-text is-description has-top-spaced-small">
|
||||
The <template x-if="form_data.resolution_fallback === 'up'"><span>higher</span></template
|
||||
><template x-if="form_data.resolution_fallback === 'down'"><span>lower</span></template> resolution will be used if
|
||||
<template x-if="form_data.resolution === '2160'"><span>4K</span></template
|
||||
><template x-if="form_data.resolution === '1440'"><span>2K</span></template
|
||||
><template x-if="form_data.resolution === '1080'"><span>1080p</span></template
|
||||
><template x-if="form_data.resolution === '720'"><span>720p</span></template
|
||||
><template x-if="form_data.resolution === '480'"><span>480p</span></template
|
||||
><template x-if="form_data.resolution === '240'"><span>240p</span></template> was not available.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Resolution -->
|
||||
|
||||
<!-- Field: Framerate -->
|
||||
<div class="ts-control is-wide has-top-spaced-large">
|
||||
<div class="label">Framerate</div>
|
||||
<div class="content">
|
||||
<div class="ts-wrap is-compact is-vertical has-top-spaced-small">
|
||||
<label class="ts-radio">
|
||||
<input name="framerate" value="60" type="radio" x-model="form_data.framerate" />
|
||||
60 FPS
|
||||
</label>
|
||||
<label class="ts-radio">
|
||||
<input name="framerate" value="30" type="radio" x-model="form_data.framerate" />
|
||||
30 FPS
|
||||
</label>
|
||||
</div>
|
||||
<template x-if="form_data.framerate === '60'">
|
||||
<div class="ts-text is-description has-top-spaced-small">30 FPS will be used if 60 FPS was not available.</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Framerate -->
|
||||
|
||||
<!-- Field: Filename Pattern -->
|
||||
<div class="ts-control is-wide has-top-spaced-large">
|
||||
<div class="label">Filename Pattern</div>
|
||||
<div class="content">
|
||||
<div class="ts-input">
|
||||
<input type="text" x-model="form_data.filename_pattern" />
|
||||
</div>
|
||||
<div class="ts-text is-description has-top-spaced-small">
|
||||
See the <a class="ts-text is-external-link is-link" href="https://github.com/teacat/chaturbate-dvr" target="_blank">README</a> for details.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Filename Pattern -->
|
||||
|
||||
<!-- Field: Check Interval -->
|
||||
<input type="hidden" x-model="form_data.interval" />
|
||||
<!-- / Field: Check Interval -->
|
||||
|
||||
<div class="ts-divider has-vertically-spaced-large"></div>
|
||||
|
||||
<!-- Field: Splitting Options -->
|
||||
<div class="ts-control is-wide has-top-spaced">
|
||||
<div class="label"></div>
|
||||
<div class="content">
|
||||
<details id="splitting-accordion" class="ts-accordion">
|
||||
<summary>Splitting Options</summary>
|
||||
<div class="ts-content is-rounded is-secondary has-top-spaced">
|
||||
<div class="ts-grid is-2-columns">
|
||||
<div class="column">
|
||||
<div class="ts-text is-bold">by Filesize</div>
|
||||
<div class="ts-input is-end-labeled has-top-spaced-small">
|
||||
<input type="text" x-model="form_data.split_filesize" />
|
||||
<span class="label">MB</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="ts-text is-bold">by Duration</div>
|
||||
<div class="ts-input is-end-labeled has-top-spaced-small">
|
||||
<input type="text" x-model="form_data.split_duration" />
|
||||
<span class="label">Mins</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ts-text is-description has-top-spaced">Splitting will be disabled if both options are 0.</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Splitting Options -->
|
||||
</div>
|
||||
<!-- / Form -->
|
||||
|
||||
<div class="ts-divider"></div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="ts-content is-secondary is-horizontally-padded">
|
||||
<div class="ts-wrap is-end-aligned">
|
||||
<button class="ts-button is-outlined is-secondary" x-on:click="closeCreateDialog">Cancel</button>
|
||||
<button class="ts-button is-primary" x-on:click="submitCreateDialog">Add Channel</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Footer -->
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocas/5.0.1/tocas.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/tocas/5.0.1/tocas.min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;500;700&display=swap" rel="stylesheet" />
|
||||
<script src="/static/script.js"></script>
|
||||
<script src="https://unpkg.com/alpinejs" defer></script>
|
||||
<title>Chaturbate DVR</title>
|
||||
</head>
|
||||
<body x-data="data()">
|
||||
<!-- Create Dialog -->
|
||||
<dialog id="create-dialog" class="ts-modal is-large" data-clickaway="close">
|
||||
<div class="content">
|
||||
<!-- Header -->
|
||||
<div class="ts-content is-horizontally-padded is-secondary">
|
||||
<div class="ts-grid">
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-header">Add Channel</div>
|
||||
</div>
|
||||
</dialog>
|
||||
<!-- / Create Dialog -->
|
||||
<div class="column">
|
||||
<button class="ts-close is-rounded is-large is-secondary" x-on:click="closeCreateDialog"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Header -->
|
||||
|
||||
<!-- Main Section -->
|
||||
<div class="ts-container is-narrow has-vertically-padded-big">
|
||||
<!-- Header -->
|
||||
<div class="ts-grid is-bottom-aligned">
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-header is-huge is-uppercased is-heavy has-leading-small">Chaturbate DVR</div>
|
||||
<div class="ts-text is-description is-bold">Version <span x-text="settings.version"></span></div>
|
||||
<div class="ts-divider"></div>
|
||||
|
||||
<!-- Form -->
|
||||
<div class="ts-content is-vertically-padded">
|
||||
<!-- Field: Channel Username -->
|
||||
<div class="ts-control is-wide">
|
||||
<div class="label">Channel Username</div>
|
||||
<div class="content">
|
||||
<div class="ts-input is-start-labeled">
|
||||
<div class="label">chaturbate.global/</div>
|
||||
<input type="text" autofocus x-model="form_data.username" />
|
||||
</div>
|
||||
<div class="ts-text is-description has-top-spaced-small">Use commas to separate multiple channel names. For example, "channel1,channel2,channel3".</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Channel Username -->
|
||||
|
||||
<!-- Field: Resolution -->
|
||||
<div class="ts-control is-wide has-top-spaced-large">
|
||||
<div class="label">Resolution</div>
|
||||
<div class="content">
|
||||
<div class="ts-grid">
|
||||
<div class="column">
|
||||
<div class="ts-select">
|
||||
<select x-model="form_data.resolution">
|
||||
<option value="2160">4K</option>
|
||||
<option value="1440">2K</option>
|
||||
<option value="1080">1080p</option>
|
||||
<option value="720">720p</option>
|
||||
<option value="540">540p</option>
|
||||
<option value="480">480p</option>
|
||||
<option value="240">240p</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="ts-wrap">
|
||||
<button class="ts-button is-outlined is-negative is-start-icon" x-on:click="terminateProgram()">
|
||||
<span class="ts-icon is-hand-icon"></span>
|
||||
Terminate
|
||||
</button>
|
||||
<button class="ts-button is-start-icon" x-on:click="openCreateDialog">
|
||||
<span class="ts-icon is-plus-icon"></span>
|
||||
Add Channel
|
||||
</button>
|
||||
</div>
|
||||
<div class="ts-select">
|
||||
<select x-model="form_data.resolution_fallback">
|
||||
<option value="up">or higher</option>
|
||||
<option value="down">or lower</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ts-text is-description has-top-spaced-small">
|
||||
The <template x-if="form_data.resolution_fallback === 'up'"><span>higher</span></template
|
||||
><template x-if="form_data.resolution_fallback === 'down'"><span>lower</span></template> resolution will be used if
|
||||
<template x-if="form_data.resolution === '2160'"><span>4K</span></template
|
||||
><template x-if="form_data.resolution === '1440'"><span>2K</span></template
|
||||
><template x-if="form_data.resolution === '1080'"><span>1080p</span></template
|
||||
><template x-if="form_data.resolution === '720'"><span>720p</span></template
|
||||
><template x-if="form_data.resolution === '480'"><span>480p</span></template
|
||||
><template x-if="form_data.resolution === '240'"><span>240p</span></template> was not available.
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Header -->
|
||||
</div>
|
||||
<!-- / Field: Resolution -->
|
||||
|
||||
<!-- Empty State -->
|
||||
<template x-if="channels.length === 0">
|
||||
<div>
|
||||
<div class="ts-divider has-vertically-spaced-large"></div>
|
||||
<div class="ts-blankslate">
|
||||
<span class="ts-icon is-eye-low-vision-icon"></span>
|
||||
<div class="header">No channel was recording</div>
|
||||
<div class="description">Add a new Chaturbate channel to start the recording.</div>
|
||||
<div class="action">
|
||||
<button class="ts-button is-start-icon" x-on:click="openCreateDialog">
|
||||
<span class="ts-icon is-plus-icon"></span>
|
||||
Add Channel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- / Empty State -->
|
||||
|
||||
<!-- Divider -->
|
||||
<template x-if="channels.length > 0">
|
||||
<div class="ts-divider is-start-text is-section">
|
||||
<span class="ts-text is-description"><span x-text="channels.length"></span> channel(s) are being recorded</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- / Divider -->
|
||||
|
||||
<div class="ts-wrap is-vertical is-relaxed">
|
||||
<!-- Channel -->
|
||||
<template x-for="channel in channels" :key="channel.username">
|
||||
<div class="ts-box is-horizontal">
|
||||
<!-- Left Section -->
|
||||
<div class="ts-content is-padded" style="flex: 1.8; display: flex; flex-direction: column">
|
||||
<!-- Header -->
|
||||
<div class="ts-grid is-middle-aligned">
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-header">
|
||||
<span x-text="channel.username"></span>
|
||||
<template x-if="channel.is_online && !channel.is_paused">
|
||||
<span class="ts-badge is-small is-start-spaced">RECORDING</span>
|
||||
</template>
|
||||
<template x-if="!channel.is_online && !channel.is_paused">
|
||||
<span class="ts-badge is-secondary is-small is-start-spaced">OFFLINE</span>
|
||||
</template>
|
||||
<template x-if="channel.is_paused">
|
||||
<span class="ts-badge is-negative is-small is-start-spaced">PAUSED</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<button class="ts-button is-secondary is-short is-outlined is-dense" x-on:click="downloadLogs(channel.username)">Download Logs</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Header -->
|
||||
|
||||
<!-- Logs -->
|
||||
<div class="ts-input has-top-spaced" style="flex: 1">
|
||||
<textarea class="has-full-height" x-bind:id="`${channel.username}-logs`" x-text="channel.logs.join('\n')" readonly></textarea>
|
||||
</div>
|
||||
<!-- / Logs -->
|
||||
</div>
|
||||
<!-- / Left Section -->
|
||||
|
||||
<div class="ts-divider is-vertical"></div>
|
||||
|
||||
<!-- Right Section -->
|
||||
<div class="ts-content is-padded has-break-all" style="flex: 1; min-width: 300px">
|
||||
<div class="ts-text is-description is-uppercased">Information</div>
|
||||
|
||||
<!-- Info: Channel URL -->
|
||||
<div class="ts-grid has-top-spaced-large">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-link-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid has-leading-small">
|
||||
<div class="ts-text is-label">Channel URL</div>
|
||||
<a class="ts-text is-link is-external-link" x-bind:href="channel.channel_url" x-text="channel.channel_url" target="_blank"></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Channel URL -->
|
||||
|
||||
<!-- Info: Filename -->
|
||||
<div class="ts-grid has-top-spaced">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-folder-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid has-leading-small">
|
||||
<div class="ts-text is-label">Filename</div>
|
||||
|
||||
<template x-if="channel.filename">
|
||||
<code class="ts-text is-code" x-text="channel.filename"></code>
|
||||
</template>
|
||||
<template x-if="!channel.filename">
|
||||
<span>-</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Filename -->
|
||||
|
||||
<!-- Info: Last streamed at -->
|
||||
<div class="ts-grid has-top-spaced">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-tower-broadcast-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-text is-label">Last streamed at</div>
|
||||
<div class="ts-text is-description">
|
||||
<span x-text="channel.last_streamed_at"></span>
|
||||
<template x-if="channel.is_online && !channel.is_paused">
|
||||
<span>(NOW)</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Last streamed at -->
|
||||
|
||||
<!-- Info: Segment duration -->
|
||||
<div class="ts-grid has-top-spaced">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-clock-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-text is-label">Segment duration</div>
|
||||
<div class="ts-text is-description">
|
||||
<span x-text="channel.segment_duration"></span>
|
||||
<template x-if="channel.split_duration !== '00:00:00'">
|
||||
<span> / <span x-text="channel.split_duration"></span></span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Segment duration -->
|
||||
|
||||
<!-- Info: Segment filesize -->
|
||||
<div class="ts-grid has-top-spaced">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-chart-pie-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-text is-label">Segment filesize</div>
|
||||
<div class="ts-text is-description">
|
||||
<span x-text="channel.segment_filesize"></span>
|
||||
<template x-if="channel.split_filesize !== '0.00 MiB'">
|
||||
<span> / <span x-text="channel.split_filesize"></span></span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Segment filesize -->
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="ts-grid is-2-columns has-top-spaced-large">
|
||||
<div class="column">
|
||||
<template x-if="!channel.is_paused">
|
||||
<button
|
||||
class="ts-button is-start-icon is-secondary is-fluid"
|
||||
x-bind:disabled="!channel.is_online"
|
||||
x-on:click="pauseChannel(channel.username)"
|
||||
>
|
||||
<span class="ts-icon is-pause-icon"></span>
|
||||
Pause
|
||||
</button>
|
||||
</template>
|
||||
<template x-if="channel.is_paused">
|
||||
<button class="ts-button is-start-icon is-fluid" x-on:click="resumeChannel(channel.username)">
|
||||
<span class="ts-icon is-play-icon"></span>
|
||||
Resume
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<div class="column">
|
||||
<button
|
||||
class="ts-button is-start-icon is-secondary is-negative is-fluid"
|
||||
data-tooltip="Stop and remove the channel from the list."
|
||||
x-on:click="deleteChannel(channel.username)"
|
||||
>
|
||||
<span class="ts-icon is-stop-icon"></span>
|
||||
Stop
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Actions -->
|
||||
</div>
|
||||
<!-- / Right Section -->
|
||||
</div>
|
||||
</template>
|
||||
<!-- / Channel -->
|
||||
<!-- Field: Framerate -->
|
||||
<div class="ts-control is-wide has-top-spaced-large">
|
||||
<div class="label">Framerate</div>
|
||||
<div class="content">
|
||||
<div class="ts-wrap is-compact is-vertical has-top-spaced-small">
|
||||
<label class="ts-radio">
|
||||
<input name="framerate" value="60" type="radio" x-model="form_data.framerate" />
|
||||
60 FPS
|
||||
</label>
|
||||
<label class="ts-radio">
|
||||
<input name="framerate" value="30" type="radio" x-model="form_data.framerate" />
|
||||
30 FPS
|
||||
</label>
|
||||
</div>
|
||||
<template x-if="form_data.framerate === '60'">
|
||||
<div class="ts-text is-description has-top-spaced-small">30 FPS will be used if 60 FPS was not available.</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Framerate -->
|
||||
|
||||
<!-- Field: Filename Pattern -->
|
||||
<div class="ts-control is-wide has-top-spaced-large">
|
||||
<div class="label">Filename Pattern</div>
|
||||
<div class="content">
|
||||
<div class="ts-input">
|
||||
<input type="text" x-model="form_data.filename_pattern" />
|
||||
</div>
|
||||
<div class="ts-text is-description has-top-spaced-small">See the <a class="ts-text is-external-link is-link" href="https://github.com/teacat/chaturbate-dvr" target="_blank">README</a> for details.</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Filename Pattern -->
|
||||
|
||||
<!-- Field: Check Interval -->
|
||||
<input type="hidden" x-model="form_data.interval" />
|
||||
<!-- / Field: Check Interval -->
|
||||
|
||||
<div class="ts-divider has-vertically-spaced-large"></div>
|
||||
|
||||
<!-- Field: Splitting Options -->
|
||||
<div class="ts-control is-wide has-top-spaced">
|
||||
<div class="label"></div>
|
||||
<div class="content">
|
||||
<details id="splitting-accordion" class="ts-accordion">
|
||||
<summary>Splitting Options</summary>
|
||||
<div class="ts-content is-rounded is-secondary has-top-spaced">
|
||||
<div class="ts-grid is-2-columns">
|
||||
<div class="column">
|
||||
<div class="ts-text is-bold">by Filesize</div>
|
||||
<div class="ts-input is-end-labeled has-top-spaced-small">
|
||||
<input type="text" x-model="form_data.split_filesize" />
|
||||
<span class="label">MB</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="ts-text is-bold">by Duration</div>
|
||||
<div class="ts-input is-end-labeled has-top-spaced-small">
|
||||
<input type="text" x-model="form_data.split_duration" />
|
||||
<span class="label">Mins</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ts-text is-description has-top-spaced">Splitting will be disabled if both options are 0.</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Field: Splitting Options -->
|
||||
</div>
|
||||
<!-- / Main Section -->
|
||||
</body>
|
||||
<!-- / Form -->
|
||||
|
||||
<div class="ts-divider"></div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="ts-content is-secondary is-horizontally-padded">
|
||||
<div class="ts-wrap is-end-aligned">
|
||||
<button class="ts-button is-outlined is-secondary" x-on:click="closeCreateDialog">Cancel</button>
|
||||
<button class="ts-button is-primary" x-on:click="submitCreateDialog">Add Channel</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Footer -->
|
||||
</div>
|
||||
</dialog>
|
||||
<!-- / Create Dialog -->
|
||||
|
||||
<!-- Main Section -->
|
||||
<div class="ts-container has-vertically-padded-big">
|
||||
<!-- Header -->
|
||||
<div class="ts-grid is-bottom-aligned">
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-header is-huge is-uppercased is-heavy has-leading-small">Chaturbate DVR</div>
|
||||
<div class="ts-text is-description is-bold">Version <span x-text="settings.version"></span></div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="ts-wrap">
|
||||
<div class="ts-select">
|
||||
<select x-model="settings.log_level">
|
||||
<option>DEBUG</option>
|
||||
<option>INFO</option>
|
||||
<option>WARN</option>
|
||||
<option>ERROR</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="ts-button is-outlined is-negative is-start-icon" x-on:click="terminateProgram()">
|
||||
<span class="ts-icon is-hand-icon"></span>
|
||||
Terminate
|
||||
</button>
|
||||
<button class="ts-button is-start-icon" x-on:click="openCreateDialog">
|
||||
<span class="ts-icon is-plus-icon"></span>
|
||||
Add Channel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Header -->
|
||||
|
||||
<!-- Empty State -->
|
||||
<template x-if="channels.length === 0">
|
||||
<div>
|
||||
<div class="ts-divider has-vertically-spaced-large"></div>
|
||||
<div class="ts-blankslate">
|
||||
<span class="ts-icon is-eye-low-vision-icon"></span>
|
||||
<div class="header">No channel was recording</div>
|
||||
<div class="description">Add a new Chaturbate channel to start the recording.</div>
|
||||
<div class="action">
|
||||
<button class="ts-button is-start-icon" x-on:click="openCreateDialog">
|
||||
<span class="ts-icon is-plus-icon"></span>
|
||||
Add Channel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- / Empty State -->
|
||||
|
||||
<!-- Divider -->
|
||||
<template x-if="channels.length > 0">
|
||||
<div class="ts-divider is-start-text is-section">
|
||||
<span class="ts-text is-description"
|
||||
><span x-text="channels.length"></span>
|
||||
<span x-show="channels.length < 2" style="display: none"> channel is</span>
|
||||
<span x-show="channels.length > 1"> channels are</span> being recorded
|
||||
</span>
|
||||
<span class="ts-text is-description"> <span x-text="channels.filter(channel => channel.is_online).length"></span> online / <span x-text="channels.filter(channel => !channel.is_online).length"></span> offline </span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- / Divider -->
|
||||
<!-- Pagination Controls -->
|
||||
<div class="ts-pagination is-fluid" style="margin-bottom: 1rem;">
|
||||
<a class="item" x-on:click="goToPage(1)" :class="{ 'is-disabled': currentPage === 1 }">«</a>
|
||||
<template x-for="page in totalPages" :key="page">
|
||||
<a class="item" x-on:click="goToPage(page)" :class="{ 'is-active': currentPage === page }" x-text="page"></a>
|
||||
</template>
|
||||
<a class="item" x-on:click="goToPage(totalPages)" :class="{ 'is-disabled': currentPage === totalPages }">»</a>
|
||||
</div>
|
||||
<!-- / Pagination controls -->
|
||||
<div class="ts-wrap is-vertical is-relaxed">
|
||||
<!-- Channel -->
|
||||
<template x-for="channel in paginatedChannels" :key="channel.username">
|
||||
<!-- <div class="ts-box is-horizontal"> -->
|
||||
<div
|
||||
class="ts-box is-horizontal"
|
||||
:class="{
|
||||
'is-positive is-top-indicated': channel.is_online && !channel.is_paused,
|
||||
'is-negative is-top-indicated': !channel.is_online && !channel.is_paused,
|
||||
'is-top-indicated': channel.is_paused
|
||||
}"
|
||||
>
|
||||
<!-- Left Section -->
|
||||
<div class="ts-content is-padded" style="flex: 1.25; display: flex; flex-direction: column">
|
||||
<!-- Header -->
|
||||
<div class="ts-grid is-middle-aligned">
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-header">
|
||||
<span x-text="channel.username"></span>
|
||||
<template x-if="channel.is_online && !channel.is_paused">
|
||||
<span class="ts-badge is-small is-start-spaced">RECORDING</span>
|
||||
</template>
|
||||
<template x-if="!channel.is_online && !channel.is_paused">
|
||||
<span class="ts-badge is-secondary is-small is-start-spaced">OFFLINE</span>
|
||||
</template>
|
||||
<template x-if="channel.is_paused">
|
||||
<span class="ts-badge is-negative is-small is-start-spaced">PAUSED</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<button class="ts-button is-secondary is-short is-outlined is-dense" x-on:click="downloadLogs(channel.username)">Download Logs</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Header -->
|
||||
|
||||
<!-- Logs -->
|
||||
<div class="ts-input has-top-spaced" style="flex: 1">
|
||||
<textarea class="has-full-height" x-bind:id="`${channel.username}-logs`" x-text="channel.logs.join('\n')" readonly></textarea>
|
||||
</div>
|
||||
<!-- / Logs -->
|
||||
</div>
|
||||
<!-- / Left Section -->
|
||||
|
||||
<div class="ts-divider is-vertical"></div>
|
||||
|
||||
<!-- Right Section -->
|
||||
<div class="ts-content is-padded has-break-all" style="flex: 1; min-width: 300px">
|
||||
<div class="ts-text is-description is-uppercased">Information</div>
|
||||
|
||||
<!-- Info: Channel URL -->
|
||||
<div class="ts-grid has-top-spaced-large">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-link-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid has-leading-small">
|
||||
<div class="ts-text is-label">Channel URL</div>
|
||||
<a class="ts-text is-link is-external-link" x-bind:href="channel.channel_url" x-text="channel.channel_url" target="_blank"></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Channel URL -->
|
||||
|
||||
<!-- Info: Filename -->
|
||||
<div class="ts-grid has-top-spaced">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-folder-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid has-leading-small">
|
||||
<div class="ts-text is-label">Filename</div>
|
||||
|
||||
<template x-if="channel.filename">
|
||||
<code class="ts-text is-code" x-text="channel.filename"></code>
|
||||
</template>
|
||||
<template x-if="!channel.filename">
|
||||
<span>-</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Filename -->
|
||||
|
||||
<!-- Info: Last streamed at -->
|
||||
<div class="ts-grid has-top-spaced">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-tower-broadcast-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-text is-label">Last streamed at</div>
|
||||
<div class="ts-text is-description">
|
||||
<span x-text="channel.last_streamed_at"></span>
|
||||
<template x-if="channel.is_online && !channel.is_paused">
|
||||
<span>(NOW)</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Last streamed at -->
|
||||
|
||||
<!-- Info: Segment duration -->
|
||||
<div class="ts-grid has-top-spaced">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-clock-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-text is-label">Segment duration</div>
|
||||
<div class="ts-text is-description">
|
||||
<span x-text="channel.segment_duration"></span>
|
||||
<template x-if="channel.split_duration !== '00:00:00'">
|
||||
<span> / <span x-text="channel.split_duration"></span></span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Segment duration -->
|
||||
|
||||
<!-- Info: Segment filesize -->
|
||||
<div class="ts-grid has-top-spaced">
|
||||
<div class="column has-leading-none" style="width: 16px">
|
||||
<span class="ts-icon is-chart-pie-icon"></span>
|
||||
</div>
|
||||
<div class="column is-fluid">
|
||||
<div class="ts-text is-label">Segment filesize</div>
|
||||
<div class="ts-text is-description">
|
||||
<span x-text="channel.segment_filesize"></span>
|
||||
<template x-if="channel.split_filesize !== '0.00 MiB'">
|
||||
<span> / <span x-text="channel.split_filesize"></span></span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Info: Segment filesize -->
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="ts-grid is-2-columns has-top-spaced-large">
|
||||
<div class="column">
|
||||
<template x-if="!channel.is_paused">
|
||||
<button class="ts-button is-start-icon is-secondary is-fluid" x-bind:disabled="!channel.is_online" x-on:click="pauseChannel(channel.username)">
|
||||
<span class="ts-icon is-pause-icon"></span>
|
||||
Pause
|
||||
</button>
|
||||
</template>
|
||||
<template x-if="channel.is_paused">
|
||||
<button class="ts-button is-start-icon is-fluid" x-on:click="resumeChannel(channel.username)">
|
||||
<span class="ts-icon is-play-icon"></span>
|
||||
Resume
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<div class="column">
|
||||
<button class="ts-button is-start-icon is-secondary is-negative is-fluid" data-tooltip="Stop and remove the channel from the list." x-on:click="deleteChannel(channel.username)">
|
||||
<span class="ts-icon is-stop-icon"></span>
|
||||
Stop
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Actions -->
|
||||
</div>
|
||||
<!-- / Right Section -->
|
||||
</div>
|
||||
</template>
|
||||
<!-- / Channel -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Main Section -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user