Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:TUM-Dev/gocast into IPraktikum-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
carlobortolan committed Jan 25, 2024
2 parents 1efd079 + e9e4108 commit 5f035a4
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 38 deletions.
46 changes: 32 additions & 14 deletions api/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,26 +359,44 @@ func (r streamRoutes) getStream(c *gin.Context) {

func (r streamRoutes) getStreamPlaylist(c *gin.Context) {
type StreamPlaylistEntry struct {
StreamID uint `json:"streamId"`
CourseSlug string `json:"courseSlug"`
StreamName string `json:"streamName"`
LiveNow bool `json:"liveNow"`
Watched bool `json:"watched"`
Start time.Time `json:"start"`
CreatedAt time.Time `json:"createdAt"`
StreamID uint `json:"streamId"`
CourseSlug string `json:"courseSlug"`
StreamName string `json:"streamName"`
LiveNow bool `json:"liveNow"`
Watched bool `json:"watched"`
Start time.Time `json:"start"`
StreamProgress model.StreamProgress `json:"streamProgress"`
CreatedAt time.Time `json:"createdAt"`
}

tumLiveContext := c.MustGet("TUMLiveContext").(tools.TUMLiveContext)

// Create mapping of stream id to progress for all progresses of user
var streamIDs []uint
for _, stream := range tumLiveContext.Course.Streams {
streamIDs = append(streamIDs, stream.ID)
}
streamProgresses := make(map[uint]model.StreamProgress)
res, err := r.LoadProgress(tumLiveContext.User.ID, streamIDs)
if err != nil {
logger.Error("Couldn't load progresses", "err", err)
} else {
for _, progress := range res {
streamProgresses[progress.StreamID] = progress
}
}

var result []StreamPlaylistEntry
for _, stream := range tumLiveContext.Course.Streams {
result = append(result, StreamPlaylistEntry{
StreamID: stream.ID,
CourseSlug: tumLiveContext.Course.Slug,
StreamName: stream.GetName(),
LiveNow: stream.LiveNow,
Watched: stream.Watched,
Start: stream.Start,
CreatedAt: stream.CreatedAt,
StreamID: stream.ID,
CourseSlug: tumLiveContext.Course.Slug,
StreamName: stream.GetName(),
LiveNow: stream.LiveNow,
Watched: stream.Watched,
Start: stream.Start,
StreamProgress: streamProgresses[stream.ID],
CreatedAt: stream.CreatedAt,
})
}

Expand Down
32 changes: 32 additions & 0 deletions api/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func configGinUsersRouter(router *gin.Engine, daoWrapper dao.DaoWrapper) {
router.POST("/api/users/settings/playbackSpeeds", routes.updatePlaybackSpeeds)
router.POST("/api/users/settings/seekingTime", routes.updateSeekingTime)
router.POST("/api/users/settings/customSpeeds", routes.updateCustomSpeeds)
router.POST("/api/users/settings/autoSkip", routes.updateAutoSkip)

router.POST("/api/users/resetPassword", routes.resetPassword)

Expand Down Expand Up @@ -723,6 +724,37 @@ func (r usersRoutes) updateSeekingTime(c *gin.Context) {
}
}

func (r usersRoutes) updateAutoSkip(c *gin.Context) {
u := c.MustGet("TUMLiveContext").(tools.TUMLiveContext).User
if u == nil {
_ = c.Error(tools.RequestError{
Status: http.StatusUnauthorized,
CustomMessage: "login required",
})
return
}
var req struct{ Value model.AutoSkipSetting }
if err := c.BindJSON(&req); err != nil {
_ = c.Error(tools.RequestError{
Status: http.StatusBadRequest,
CustomMessage: "can not bind body to request",
Err: err,
})
return
}

settingBytes, _ := json.Marshal(req.Value)
err := r.DaoWrapper.UsersDao.AddUserSetting(&model.UserSetting{UserID: u.ID, Type: model.AutoSkip, Value: string(settingBytes)})
if err != nil {
_ = c.Error(tools.RequestError{
Status: http.StatusInternalServerError,
CustomMessage: "can not add user setting",
Err: err,
})
return
}
}

func (r usersRoutes) exportPersonalData(c *gin.Context) {
var resp personalData
u := c.MustGet("TUMLiveContext").(tools.TUMLiveContext).User
Expand Down
4 changes: 3 additions & 1 deletion docs/static/tum-live-starter.sql
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ CREATE TABLE `lecture_halls` (

LOCK TABLES `lecture_halls` WRITE;
/*!40000 ALTER TABLE `lecture_halls` DISABLE KEYS */;
INSERT INTO `lecture_halls` VALUES (1,NULL,NULL,NULL,'HS001','Hörsaal 001',NULL,NULL,NULL,NULL,NULL,NULL,NULL);
/*!40000 ALTER TABLE `lecture_halls` ENABLE KEYS */;
UNLOCK TABLES;

Expand Down Expand Up @@ -606,6 +607,7 @@ CREATE TABLE `silences` (

LOCK TABLES `silences` WRITE;
/*!40000 ALTER TABLE `silences` DISABLE KEYS */;
INSERT INTO `silences` VALUES (1,'2024-01-14 21:16:37.000','2024-01-14 21:16:43.000',NULL,0,100,1),(2,'2024-01-14 21:17:00.000','2024-01-14 21:17:02.000',NULL,0,200,2);
/*!40000 ALTER TABLE `silences` ENABLE KEYS */;
UNLOCK TABLES;

Expand Down Expand Up @@ -813,7 +815,7 @@ CREATE TABLE `streams` (

LOCK TABLES `streams` WRITE;
/*!40000 ALTER TABLE `streams` DISABLE KEYS */;
INSERT INTO `streams` VALUES (1,'2022-04-18 13:45:58.657','2022-04-18 13:46:46.547',NULL,'VL 1: Was ist Bier?','',1,'2022-04-11 12:00:00.000','2022-04-11 13:00:00.000','','','',0,NULL,'c33dfc976efb410299e604b255db0127','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',0,1,NULL,NULL,0,NULL,NULL,NULL,0,'',NULL),(2,'2022-04-18 13:46:25.841','2022-04-18 13:46:46.547',NULL,'VL 2: Wie mache ich Bier?','',1,'2022-04-18 12:00:00.000','2022-04-18 13:00:00.000','','','',0,NULL,'5815366e4010482687912588349bc5c0','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',0,1,NULL,NULL,0,NULL,NULL,NULL,0,'',NULL),(4,'2022-04-18 13:46:46.547','2022-04-18 13:46:46.547',NULL,'VL 3: Rückblick','',1,'2026-02-19 12:00:00.000','2026-02-19 13:00:00.000','','','',0,NULL,'d8ce0b882dbc4d999b42c143ce07db5a','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',0,0,NULL,NULL,0,NULL,NULL,NULL,0,'',NULL),(7,'2022-04-18 13:46:46.547','2022-04-18 13:46:46.547',NULL,'VL 1: Livestream','',2,'2022-02-19 12:00:00.000','2022-02-19 13:00:00.000','','','',0,NULL,'','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',1,0,NULL,NULL,0,NULL,NULL,NULL,0,'',NULL),(8,'2022-04-18 13:46:46.547','2022-04-18 13:46:46.547',NULL,'VL 1: Intro to Go','',3,'2022-02-19 12:00:00.000','2022-02-19 12:00:00.000','','','',0,NULL,'d8ce0b882dbc4d999b42c143ce07db5a','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',0,1,NULL,NULL,0,NULL,NULL,NULL,0,'',NULL);
INSERT INTO `streams` VALUES (1,'2022-04-18 13:45:58.657','2022-04-18 13:46:46.547',NULL,'VL 1: Was ist Bier?','',1,'2022-04-11 12:00:00.000','2022-04-11 12:09:56.000','','','',0,NULL,'c33dfc976efb410299e604b255db0127','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',0,1,NULL,NULL,0,NULL,NULL,1,0,'',NULL),(2,'2022-04-18 13:46:25.841','2022-04-18 13:46:46.547',NULL,'VL 2: Wie mache ich Bier?','',1,'2022-04-18 12:00:00.000','2022-04-18 12:09:56.000','','','',0,NULL,'5815366e4010482687912588349bc5c0','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',0,1,NULL,NULL,0,NULL,NULL,1,0,'',NULL),(4,'2022-04-18 13:46:46.547','2022-04-18 13:46:46.547',NULL,'VL 3: Rückblick','',1,'2026-02-19 12:00:00.000','2026-02-19 13:00:00.000','','','',0,NULL,'d8ce0b882dbc4d999b42c143ce07db5a','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',0,0,NULL,NULL,0,NULL,NULL,1,0,'',NULL),(7,'2022-04-18 13:46:46.547','2022-04-18 13:46:46.547',NULL,'VL 1: Livestream','',2,'2022-02-19 12:00:00.000','2022-02-19 13:00:00.000','','','',0,NULL,'','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',1,0,NULL,NULL,0,NULL,NULL,1,0,'',NULL),(8,'2022-04-18 13:46:46.547','2022-04-18 13:46:46.547',NULL,'VL 1: Intro to Go','',3,'2022-02-19 12:00:00.000','2022-02-19 12:00:00.000','','','',0,NULL,'d8ce0b882dbc4d999b42c143ce07db5a','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','https://stream.lrz.de/vod/_definst_/mp4:tum/RBG/bb.mp4/playlist.m3u8','',0,1,NULL,NULL,0,NULL,NULL,1,0,'',NULL);
/*!40000 ALTER TABLE `streams` ENABLE KEYS */;
UNLOCK TABLES;

Expand Down
15 changes: 15 additions & 0 deletions model/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,18 @@ func (s Stream) ToDTO() StreamDTO {
Duration: duration,
}
}

// FirstSilenceAsProgress returns the end of the first silence as a quotient of the length of the stream
func (s Stream) FirstSilenceAsProgress() float64 {
if len(s.Silences) == 0 {
return 0
}
// Sanity check: first silence at beginning of stream
if s.Silences[0].Start != 0 {
return 0
}
duration := s.End.Sub(s.Start).Seconds()
p := float64(s.Silences[0].End) / duration

return p
}
21 changes: 21 additions & 0 deletions model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const (
CustomPlaybackSpeeds
SeekingTime
UserDefinedSpeeds
AutoSkip
)

type UserSetting struct {
Expand Down Expand Up @@ -197,6 +198,26 @@ func (u User) PreferredNameChangeAllowed() bool {
return true
}

// AutoSkipSetting wraps whether auto skip is enabled in JSON
type AutoSkipSetting struct {
Enabled bool `json:"enabled"`
}

// GetAutoSkipEnabled returns whether the user has enabled auto skip
func (u User) GetAutoSkipEnabled() (AutoSkipSetting, error) {
for _, setting := range u.Settings {
if setting.Type == AutoSkip {
var a AutoSkipSetting
err := json.Unmarshal([]byte(setting.Value), &a)
if err != nil {
return AutoSkipSetting{Enabled: false}, err
}
return a, nil
}
}
return AutoSkipSetting{Enabled: false}, nil
}

type argonParams struct {
memory uint32
iterations uint32
Expand Down
9 changes: 8 additions & 1 deletion web/assets/css/home.css
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,20 @@
}

.tum-live-menu .tum-live-menu-item {
@apply flex items-center p-2 hover:bg-gray-100 dark:hover:bg-gray-800 my-2 w-full
@apply flex items-center py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-800 my-2 w-full
}

.tum-live-menu .tum-live-menu-item.active {
@apply bg-gray-100 dark:bg-gray-800
}

.tum-live-menu .tum-live-menu-item .icon-wrapper {
width: 18px;
display: flex;
justify-content: center;
align-items: center;
}


.tum-live-course-list > header {
@apply flex items-center justify-between mb-8
Expand Down
4 changes: 2 additions & 2 deletions web/assets/css/watch.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.playlist-thumbnail {
@apply bg-gray-100 dark:bg-gray-800 rounded-lg mr-4 bg-cover transition-all duration-500 hover:shadow-xl dark:shadow-gray-900/75;
@apply relative bg-gray-100 dark:bg-gray-800 rounded-lg mr-4 bg-cover transition-all duration-500 hover:shadow-xl dark:shadow-gray-900/75;
}

/* Rendered, but not visible on the screen. Enables layout calculations. */
Expand All @@ -10,4 +10,4 @@
width: 100%;
height: auto;
overflow: visible;
}
}
26 changes: 13 additions & 13 deletions web/template/home.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
{{if or (eq $user.Role 1) (eq $user.Role 2) }}
<a href="/admin"
class="tum-live-menu-item">
<div style="width: 30px; display: flex; justify-content: center; align-items: center;">
<i class="fa-solid fa-hammer mr-3"></i>
<div class="icon-wrapper mr-2">
<i class="fa-solid fa-hammer"></i>
</div>
<p>Admin</p>
</a>
Expand All @@ -95,8 +95,8 @@
<button type="button"
class="tum-live-menu-item"
@click="userContext.getChild('themePicker').toggle()">
<div style="width: 30px; display: flex; justify-content: center; align-items: center;">
<i class="fa-regular fa-moon mr-3"></i>
<div class="icon-wrapper mr-2">
<i class="fa-regular fa-moon"></i>
</div>
<span>Theme</span>
<i class="fa-solid ml-auto"
Expand All @@ -106,7 +106,7 @@
<template x-for="[modeId, mode] of Object.entries($store.theme.modes)"
:key="modeId">
<button type="button" tabindex="0"
class="text-left hover:bg-gray-100 dark:hover:bg-gray-800 py-2 px-4"
class="text-left hover:bg-gray-100 dark:hover:bg-gray-800 py-1 px-10"
:class="{'bg-gray-100 dark:bg-gray-800': modeId === $store.theme.activeTheme}"
@click="$store.theme.setTheme(modeId)"
x-text="mode.name">
Expand All @@ -116,33 +116,33 @@
</div>
<a href="/settings"
class="tum-live-menu-item">
<div style="width: 30px; display: flex; justify-content: center; align-items: center;">
<i class="fa-solid fa-gear mr-3"></i>
<div class="icon-wrapper mr-2">
<i class="fa-solid fa-gear"></i>
</div>
<p>Settings</p>
</a>
<div class="border-b dark:border-gray-800"></div>
<a href="https://github.com/TUM-Dev/gocast"
target="_blank"
class="tum-live-menu-item">
<div style="width: 30px; display: flex; justify-content: center; align-items: center;">
<i class="fa-regular fa-comment mr-3"></i>
<div class="icon-wrapper mr-2">
<i class="fa-regular fa-comment"></i>
</div>
<p>Send Feedback</p>
</a>
<a href="https://github.com/TUM-Dev/gocast/issues/new?assignees=&labels=&template=bug_report.md&title="
class="tum-live-menu-item"
target="_blank">
<div style="width: 30px; display: flex; justify-content: center; align-items: center;">
<i class="fa-brands fa-github mr-3"></i>
<div class="icon-wrapper mr-2">
<i class="fa-brands fa-github"></i>
</div>
<p>Report problem</p>
</a>
<div class="border-b dark:border-gray-800"></div>
<a href="/logout"
class="tum-live-menu-item">
<div style="width: 30px; display: flex; justify-content: center; align-items: center;">
<i class="fa-solid fa-sign-out mr-3"></i>
<div class="icon-wrapper mr-2">
<i class="fa-solid fa-sign-out"></i>
</div>
<p>Logout</p>
</a>
Expand Down
9 changes: 9 additions & 0 deletions web/template/partial/stream/playlist.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@
<div
:style="`background-image:url('/api/stream/${elem.streamId}/thumbs/vod')`"
class="h-14 w-24 shrink-0 playlist-thumbnail">
<div :id="`vod-progress-${elem.streamId}`"
class="tum-live-thumbnail-progress">
<div>
<template x-if="elem.progress !== undefined">
<span :style="`width: ${elem.progress.Percentage()}%`"
:class="{'rounded-br-lg': elem.progress.HasProgressOne()}"></span>
</template>
</div>
</div>
</div>
<i x-show="selected" class="fa-solid fa-play text-2 mr-2"></i>
<h2 x-text="elem.streamName" class="text-sm dark:text-white"></h2>
Expand Down
15 changes: 15 additions & 0 deletions web/template/user-settings.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,21 @@
<label for="seek-time-20">20s</label>
</div>
</section>
<section x-data="{ autoSkip: {{toJson .TUMLiveContext.User.GetAutoSkipEnabled}} }">
<h2>Automatically Skip First Silence</h2>
<span class="mr-2">
<label class="relative inline-flex items-center cursor-pointer">
<input :checked="autoSkip.enabled" type="checkbox" x-model="autoSkip.enabled" class="sr-only peer"
@change="global.updatePreference(global.UserSetting.AutoSkip, autoSkip)"/>
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-600
dark:peer-focus:ring-indigo-600 rounded-full peer dark:bg-gray-600 peer-checked:after:translate-x-full
peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px]
after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5
after:transition-all dark:border-gray-600 peer-checked:bg-blue-600 dark:peer-checked:bg-indigo-600"></div>
<span class="ml-3 text-sm font-medium text-3">Skip</span>
</label>
</span>
</section>
<section>
<h2>Privacy & Data Protection</h2>
<a href="/api/users/exportData" download="personal_data.json"
Expand Down
Loading

0 comments on commit 5f035a4

Please sign in to comment.