-
Notifications
You must be signed in to change notification settings - Fork 718
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12586 from nikkuAg/bloom-player
Bloom player
- Loading branch information
Showing
24 changed files
with
778 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
kolibri/core/content/migrations/0038_alter_localfile_extension.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Generated by Django 3.2.25 on 2024-09-25 09:03 | ||
from django.db import migrations | ||
from django.db import models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
("content", "0037_add_bloompub_preset"), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name="localfile", | ||
name="extension", | ||
field=models.CharField( | ||
blank=True, | ||
choices=[ | ||
("mp4", "MP4 Video"), | ||
("webm", "WEBM Video"), | ||
("vtt", "VTT Subtitle"), | ||
("mp3", "MP3 Audio"), | ||
("pdf", "PDF Document"), | ||
("jpg", "JPG Image"), | ||
("jpeg", "JPEG Image"), | ||
("png", "PNG Image"), | ||
("gif", "GIF Image"), | ||
("json", "JSON"), | ||
("svg", "SVG Image"), | ||
("perseus", "Perseus Exercise"), | ||
("graphie", "Graphie Exercise"), | ||
("zip", "HTML5 Zip"), | ||
("h5p", "H5P"), | ||
("zim", "ZIM"), | ||
("epub", "ePub Document"), | ||
("bloompub", "Bloom Document"), | ||
("bloomd", "Bloom Document"), | ||
], | ||
max_length=40, | ||
), | ||
), | ||
] |
116 changes: 116 additions & 0 deletions
116
kolibri/core/content/static/bloom/bloomPlayer-d1be6dab31acb4a956a6.min.js
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
</head> | ||
<body style="background-color: #2e2e2e"> | ||
<div id="root"><span style="color: #d65649">Loading Bloom Player...</span></div> | ||
<script | ||
type="text/javascript" | ||
src="bloomPlayer-d1be6dab31acb4a956a6.min.js" | ||
></script> | ||
</body> | ||
</html> |
Binary file added
BIN
+56.7 KB
kolibri/core/content/static/bloom/right_answer-913c37e88e2939122d763361833efd24.mp3
Binary file not shown.
Binary file added
BIN
+25.7 KB
kolibri/core/content/static/bloom/wrong_answer-f96cfc1e0cc2cea2dd523d521d4c8738.mp3
Binary file not shown.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import BloomPubComponent from './views/BloomPubRendererIndex.vue'; | ||
import ContentRendererModule from 'content_renderer_module'; | ||
|
||
class BloomPubModule extends ContentRendererModule { | ||
get rendererComponent() { | ||
return BloomPubComponent; | ||
} | ||
} | ||
|
||
const bloomPubModule = new BloomPubModule(); | ||
|
||
export { bloomPubModule as default }; |
275 changes: 275 additions & 0 deletions
275
kolibri/plugins/bloompub_viewer/assets/src/views/BloomPubRendererIndex.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
<template> | ||
|
||
<CoreFullscreen | ||
ref="bloompubRenderer" | ||
class="bloompub-renderer" | ||
:style="{ width: iframeWidth }" | ||
@changeFullscreen="isInFullscreen = $event" | ||
> | ||
<div | ||
class="fullscreen-header" | ||
:style="{ backgroundColor: $themePalette.grey.v_100 }" | ||
> | ||
<KButton | ||
:primary="false" | ||
appearance="flat-button" | ||
@click="$refs.bloompubRenderer.toggleFullscreen()" | ||
> | ||
<KIcon | ||
v-if="isInFullscreen" | ||
icon="fullscreen_exit" | ||
class="fs-icon" | ||
/> | ||
<KIcon | ||
v-else | ||
icon="fullscreen" | ||
class="fs-icon" | ||
/> | ||
{{ fullscreenText }} | ||
</KButton> | ||
</div> | ||
<div | ||
class="iframe-container" | ||
:style="containerStyle" | ||
> | ||
<iframe | ||
ref="iframe" | ||
class="iframe" | ||
sandbox="allow-scripts allow-same-origin" | ||
:style="{ backgroundColor: $themePalette.grey.v_100 }" | ||
frameBorder="0" | ||
:src="rooturl" | ||
allow="fullscreen" | ||
> | ||
</iframe> | ||
<KCircularLoader | ||
v-if="loading" | ||
:delay="false" | ||
class="loader" | ||
/> | ||
</div> | ||
</CoreFullscreen> | ||
|
||
</template> | ||
|
||
|
||
<script> | ||
import urls from 'kolibri.urls'; | ||
import { now } from 'kolibri.utils.serverClock'; | ||
import CoreFullscreen from 'kolibri.coreVue.components.CoreFullscreen'; | ||
import Hashi from 'hashi'; | ||
const defaultContentHeight = '500px'; | ||
const frameTopbarHeight = '37px'; | ||
export default { | ||
name: 'BloomPubRendererIndex', | ||
components: { | ||
CoreFullscreen, | ||
}, | ||
props: { | ||
userId: { | ||
type: String, | ||
default: '', | ||
}, | ||
userFullName: { | ||
type: String, | ||
default: '', | ||
}, | ||
progress: { | ||
type: Number, | ||
default: 0, | ||
}, | ||
}, | ||
data() { | ||
return { | ||
iframeHeight: (this.options && this.options.height) || defaultContentHeight, | ||
isInFullscreen: false, | ||
loading: false, | ||
}; | ||
}, | ||
computed: { | ||
rooturl() { | ||
return urls.hashi(); | ||
}, | ||
iframeWidth() { | ||
return (this.options && this.options.width) || 'auto'; | ||
}, | ||
fullscreenText() { | ||
return this.isInFullscreen ? this.$tr('exitFullscreen') : this.$tr('enterFullscreen'); | ||
}, | ||
userData() { | ||
return { | ||
userId: this.userId, | ||
userFullName: this.userFullName, | ||
progress: this.progress, | ||
complete: this.progress >= 1, | ||
language: this.lang.id, | ||
timeSpent: this.timeSpent, | ||
}; | ||
}, | ||
containerStyle() { | ||
if (this.isInFullscreen) { | ||
return { | ||
position: 'absolute', | ||
top: frameTopbarHeight, | ||
bottom: 0, | ||
}; | ||
} | ||
return {}; | ||
}, | ||
/* eslint-disable kolibri/vue-no-unused-properties */ | ||
/** | ||
* @public | ||
* Note: the default duration historically for HTML5 Apps has been 5 min | ||
*/ | ||
defaultDuration() { | ||
return 300; | ||
}, | ||
/* eslint-enable kolibri/vue-no-unused-properties */ | ||
entry() { | ||
return (this.options && this.options.entry) || 'index.htm'; | ||
}, | ||
isBloom() { | ||
return this.defaultFile.extension === 'bloompub'; | ||
}, | ||
}, | ||
watch: { | ||
userData(newValue) { | ||
if (newValue && this.hashi) { | ||
this.hashi.updateData({ userData: newValue }); | ||
} | ||
}, | ||
}, | ||
mounted() { | ||
this.hashi = new Hashi({ iframe: this.$refs.iframe, now }); | ||
this.hashi.onUserDataUpdate(data => { | ||
const hashiProgress = data.progress; | ||
if (hashiProgress !== null && !this.forceDurationBasedProgress) { | ||
this.$emit('updateProgress', hashiProgress); | ||
} | ||
}); | ||
this.hashi.on('navigateTo', message => { | ||
this.$emit('navigateTo', message); | ||
}); | ||
this.hashi.on(this.hashi.events.RESIZE, scrollHeight => { | ||
this.iframeHeight = scrollHeight; | ||
}); | ||
this.hashi.on(this.hashi.events.LOADING, loading => { | ||
this.loading = loading; | ||
}); | ||
this.hashi.on(this.hashi.events.ERROR, err => { | ||
this.loading = false; | ||
this.$emit('error', err); | ||
}); | ||
let storageUrl = this.defaultFile.storage_url; | ||
if (!this.isBloom) { | ||
// In the case that this is being routed via a remote URL | ||
// ensure we preserve that for the zip endpoint. | ||
const url = new URL(this.defaultFile.storage_url, window.location.href); | ||
const baseurl = url.searchParams.get('baseurl'); | ||
storageUrl = urls.zipContentUrl( | ||
this.defaultFile.checksum, | ||
this.defaultFile.extension, | ||
this.entry, | ||
baseurl ? encodeURIComponent(baseurl) : undefined, | ||
); | ||
} | ||
this.hashi.initialize( | ||
(this.extraFields && this.extraFields.contentState) || {}, | ||
this.userData, | ||
storageUrl, | ||
this.defaultFile.checksum, | ||
); | ||
this.$emit('startTracking'); | ||
if (!this.isBloom) { | ||
this.pollProgress(); | ||
} | ||
}, | ||
beforeDestroy() { | ||
if (this.timeout) { | ||
clearTimeout(this.timeout); | ||
} | ||
this.$emit('stopTracking'); | ||
}, | ||
methods: { | ||
recordProgress() { | ||
let progress; | ||
if (this.forceDurationBasedProgress) { | ||
progress = this.durationBasedProgress; | ||
} else { | ||
const hashiProgress = this.hashi ? this.hashi.getProgress() : null; | ||
progress = hashiProgress === null ? this.durationBasedProgress : hashiProgress; | ||
} | ||
this.$emit('updateProgress', progress); | ||
if (progress >= 1) { | ||
this.$emit('finished'); | ||
} | ||
this.pollProgress(); | ||
}, | ||
pollProgress() { | ||
this.timeout = setTimeout(() => { | ||
this.recordProgress(); | ||
}, 5000); | ||
}, | ||
}, | ||
$trs: { | ||
exitFullscreen: { | ||
message: 'Exit fullscreen', | ||
context: | ||
"Learners can use the Esc key or the 'exit fullscreen' button to close the fullscreen view on an html5 app.", | ||
}, | ||
enterFullscreen: { | ||
message: 'Enter fullscreen', | ||
context: | ||
'Learners can use the full screen button in the upper right corner to open an html5 app in fullscreen view.\n', | ||
}, | ||
}, | ||
}; | ||
</script> | ||
|
||
|
||
<style lang="scss" scoped> | ||
@import '~kolibri-design-system/lib/styles/definitions'; | ||
$frame-topbar-height: 37px; | ||
.fullscreen-header { | ||
text-align: right; | ||
} | ||
.fs-icon { | ||
position: relative; | ||
top: 8px; | ||
width: 24px; | ||
height: 24px; | ||
} | ||
.bloompub-renderer { | ||
position: relative; | ||
text-align: center; | ||
} | ||
.iframe { | ||
width: 100%; | ||
height: 100%; | ||
} | ||
.iframe-container { | ||
@extend %momentum-scroll; | ||
width: 100%; | ||
height: calc(100% - #{$frame-topbar-height}); | ||
margin-bottom: -8px; | ||
overflow: hidden; | ||
} | ||
.loader { | ||
position: absolute; | ||
top: calc(50% - 16px); | ||
left: calc(50% - 16px); | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = { | ||
bundle_id: 'main', | ||
webpack_config: { | ||
entry: './assets/src/module.js', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from le_utils.constants import format_presets | ||
|
||
from kolibri.core.content import hooks as content_hooks | ||
from kolibri.plugins import KolibriPluginBase | ||
from kolibri.plugins.hooks import register_hook | ||
|
||
|
||
class BloomPubRenderPlugin(KolibriPluginBase): | ||
pass | ||
|
||
|
||
@register_hook | ||
class BloomPubRenderAsset(content_hooks.ContentRendererHook): | ||
bundle_id = "main" | ||
presets = (format_presets.BLOOMPUB,) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.