Commit c92ff533 authored by Curtis Adam's avatar Curtis Adam

Display active cards as a cube in 3D mode

parent b427e45d
......@@ -11,6 +11,7 @@
@import '../imports/ui/cardset/cardset.scss';
@import '../imports/ui/filter/index/item/cardset.scss';
@import '../imports/ui/card/card.scss';
@import '../imports/ui/card/cube/cube.scss';
@import '../imports/ui/card/navigation/navigation.scss';
@import '../imports/ui/card/editor/editor.scss';
@import '../imports/ui/card/sidebar/sidebar.scss';
......
......@@ -475,6 +475,8 @@ $themes: (
$card_navigation_text: map-get($map, "card_navigation_text");
$card_navigation_background_hover: map-get($map, "card_navigation_background_hover");
$card_navigation_text_hover: map-get($map, "card_navigation_text_hover");
//cube colors
$cube_border: map-get($map, "cube_border");
//card colors
$background_mobile_preview: map-get($map, "background_mobile_preview");
$background_lecture: map-get($map, "background_lecture");
......@@ -3443,5 +3445,9 @@ $themes: (
background: $barfy_stars_particles_5;
}
}
//cube colors
.flashcard-3d {
border-color: $cube_border;
}
}
}
......@@ -359,6 +359,8 @@
"card_navigation_text": $primary_text,
"card_navigation_background_hover": $button_background_hover,
"card_navigation_text_hover": $button_text_hover,
//cube colors
"cube_border": $thm_gray,
//card colors
"background_mobile_preview": $btn_inactive,
"background_lecture": LightGoldenRodYellow,
......
......@@ -32,7 +32,8 @@ export let CardIndex = class CardIndex {
if (Session.get('activeCard') === undefined && result[0] !== undefined) {
CardNavigation.setActiveCardData(result[0]._id);
}
return CardVisuals.setTypeAndDifficulty(result);
Session.set('activeIndexCards', CardVisuals.setTypeAndDifficulty(result));
return Session.get('activeIndexCards');
}
static getCardIndex () {
......
......@@ -9,6 +9,7 @@ import {Cards} from "./cards";
import {Cardsets} from "./cardsets";
import {SweetAlertMessages} from "./sweetAlert";
import {CardType} from "./cardTypes";
import {NavigatorCheck} from "./navigatorCheck";
let keyEventsUnlocked = true;
let lastActiveCardString = "lastActiveCard";
......@@ -20,17 +21,29 @@ export let CardNavigation = class CardNavigation {
$(".cardNavigation > li:nth-child(" + index + ") a").click();
}
static switchCardSide (contentId, navigationId, cardStyle) {
CardVisuals.toggleZoomContainer(true);
CardVisuals.toggleAspectRatioContainer(true);
CardVisuals.isTextCentered();
Session.set('dictionaryBeolingus', 0);
Session.set('dictionaryLinguee', 0);
Session.set('dictionaryGoogle', 0);
Session.set('activeCardStyle', cardStyle);
Session.set('activeCardContentId', contentId);
this.setActiveNavigationButton(navigationId);
CardEditor.setEditorContent(navigationId);
static switchCardSide (contentId, navigationId, cardStyle, cardSide) {
let allowTrigger = true;
if (!NavigatorCheck.gotFeatureSupport(5) && Session.get('is3DTransitionActive') && Session.get('is3DActive')) {
allowTrigger = false;
}
if (allowTrigger) {
CardVisuals.toggleZoomContainer(true);
CardVisuals.toggleAspectRatioContainer(true);
CardVisuals.isTextCentered();
Session.set('dictionaryBeolingus', 0);
Session.set('dictionaryLinguee', 0);
Session.set('dictionaryGoogle', 0);
Session.set('activeCardStyle', cardStyle);
Session.set('activeCardContentId', contentId);
this.setActiveNavigationButton(navigationId);
CardEditor.setEditorContent(navigationId);
if (Session.get('is3DActive')) {
if (!NavigatorCheck.gotFeatureSupport(5)) {
Session.set('is3DTransitionActive', 1);
}
CardVisuals.rotateCube(cardSide);
}
}
}
static setActiveNavigationButton (index) {
......@@ -38,6 +51,23 @@ export let CardNavigation = class CardNavigation {
$(".cardNavigation > li:nth-child(" + index + ") a").removeClass('switchCardSide').addClass('card-navigation-active');
}
static getCubeSidePosition (index) {
switch (index) {
case 0:
return "front";
case 1:
return "right";
case 2:
return "back";
case 3:
return "left";
case 4:
return "top";
case 5:
return "bottom";
}
}
static filterNavigation (cubeSides, mode = undefined) {
if (cubeSides === undefined) {
return [""];
......@@ -56,6 +86,7 @@ export let CardNavigation = class CardNavigation {
filteredSides.push(cubeSides[i]);
}
}
cubeSides[i].side = this.getCubeSidePosition(i);
}
return filteredSides;
}
......@@ -70,6 +101,7 @@ export let CardNavigation = class CardNavigation {
if (cubeSides[i].isAnswerFocus) {
Session.set('answerFocus', (i + 1));
}
cubeSides[i].side = this.getCubeSidePosition(i);
}
return cubeSides;
}
......
import {Session} from "meteor/session";
import {Cardsets} from "./cardsets.js";
import * as config from "../config/cardTypes.js";
import {CardNavigation} from "./cardNavigation";
export let CardType = class CardType {
static getCardTypesOrder () {
......@@ -42,10 +43,14 @@ export let CardType = class CardType {
}
}
} else {
let index = CardNavigation.getCardSideNavigationIndex() - 1;
if (index === undefined || index < 0 || index > cubeSides.length) {
index = 0;
}
if (type) {
return cubeSides[0].defaultStyle;
return cubeSides[index].defaultStyle;
} else {
return cubeSides[0].contentId;
return cubeSides[index].contentId;
}
}
}
......@@ -86,6 +91,50 @@ export let CardType = class CardType {
}
}
static getCubeSideID (side) {
switch (side) {
case "front":
return 0;
case "right":
return 1;
case "back":
return 2;
case "left":
return 3;
case "top":
return 4;
case "bottom":
return 5;
}
}
static getSideData (cardType, forceSide) {
let sides = this.getCardTypeCubeSides(cardType);
let id = this.getCubeSideID(forceSide);
return sides[id];
}
static getContentID (card) {
if (card.forceSide) {
let sideData = this.getSideData(card.cardType, card.forceSide);
if (sideData !== undefined) {
return sideData.contentId;
}
} else {
if (card.isActive) {
return Session.get('activeCardContentId');
} else {
return this.getCardTypeCubeSides(card.cardType)[0].contentId;
}
}
}
static getContentStyle (cardType, forceSide) {
let sideData = this.getSideData(cardType, forceSide);
if (sideData !== undefined) {
return sideData.defaultStyle;
}
}
static gotLearningUnit (cardType) {
return config.cardTypesWithLearningUnit.includes(cardType);
}
......
This diff is collapsed.
......@@ -54,7 +54,7 @@ export let MarkdeepEditor = class MarkdeepEditor {
}
static changeBackgroundStyle () {
if (Session.get('backgroundStyle') == 1) {
if (Session.get('backgroundStyle') === 1) {
Session.set('backgroundStyle', 0);
} else {
Session.set('backgroundStyle', 1);
......
......@@ -130,6 +130,20 @@ export let PomodoroTimer = class PomodoroTimer {
return 30 * (date.getHours() % 12) + date.getMinutes() / 2;
}
static updateArcs () {
let d = new Date();
if (pomRunning) {
/*goes and draws the necessary arcs around the circle*/
$(".progressArc").attr("d", this.describeArc(50, 50, 44, pomBeginAngle, endPom));
$(".pomArc").attr("d", this.describeArc(50, 50, 44, 6 * d.getMinutes() + d.getSeconds() / 10, endPom));
$(".breakArc").attr("d", this.describeArc(50, 50, 44, endPom, endBreak));
} else {
$(".pomArc").attr("d", this.describeArc(0, 0, 0, 0, 0));
$(".progressArc").attr("d", this.describeArc(0, 0, 0, 0, 0));
$(".breakArc").attr("d", this.describeArc(0, 0, 0, 0, 0));
}
}
/*the arcs around the clock get redrawn every second, as do the hands on the clock, thanks to this setInterval function. It runs every second.*/
static interval () {
/*here, we get the current time, and since there are 360 degrees around a circle, and 60 minutes in an hour, each minute is 360/60 = 6 degrees of rotation. multiply that by the number of minutes and add the seconds and their corresponding degree value and you get a minute hand that moves every second. Similar with the hour hand.*/
......@@ -153,12 +167,7 @@ export let PomodoroTimer = class PomodoroTimer {
}
/*this function runs every second as the work period progresses.*/
if (pomRunning) {
/*goes and draws the necessary arcs around the circle*/
$(".progressArc").attr("d", this.describeArc(50, 50, 44, pomBeginAngle, endPom));
$(".pomArc").attr("d", this.describeArc(50, 50, 44, 6 * d.getMinutes() + d.getSeconds() / 10, endPom));
$(".breakArc").attr("d", this.describeArc(50, 50, 44, endPom, endBreak));
}
this.updateArcs();
/*this is the trigger to end the work period. it ends when the polar coodinates of the minute hand match the polar coodinates of the end of the work arc*/
if ((6 * d.getMinutes() + d.getSeconds() / 10 >= endPom - 0.1 && 6 * d.getMinutes() + d.getSeconds() / 10 <= endPom + 0.1) && pomRunning) {
......@@ -173,9 +182,7 @@ export let PomodoroTimer = class PomodoroTimer {
totalPoms++;
/*erase all the arcs, because you want the next period to start when the confirm button is clicked, not immediately after the previous period. That gives you time to finish what you were doing without being penalized.*/
$(".pomArc").attr("d", this.describeArc(0, 0, 0, 0, 0));
$(".progressArc").attr("d", this.describeArc(0, 0, 0, 0, 0));
$(".breakArc").attr("d", this.describeArc(0, 0, 0, 0, 0));
this.updateArcs();
/*the first sweet alert! This is what pops up when you finish a pomodoro. It congradulates the user and lets them start their break when they are ready. There is no option to stop the session in this box, that function is relegated to the second click on the clock, as noted by the title.*/
if (Route.isPresentation() || Route.isDemo()) {
......
......@@ -60,26 +60,22 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default",
"gotLearningGoalPlaceholder": true
},
{
"contentId": 4,
"side": "right",
"defaultStyle": "default",
"isAnswer": true
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
},
{
"contentId": 3,
"side": "left",
"defaultStyle": "default",
"isAnswer": true
}
......@@ -89,13 +85,11 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default",
"defaultTextAlign": "center"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"defaultTextAlign": "center",
"isAnswer": true,
......@@ -106,17 +100,14 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default"
},
{
"contentId": 3,
"side": "left",
"defaultStyle": "default"
}
],
......@@ -124,13 +115,11 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default",
"defaultTextAlign": "center"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"defaultTextAlign": "center",
"isAnswer": true,
......@@ -138,7 +127,6 @@ let cardTypeCubeSides = [
},
{
"contentId": 3,
"side": "left",
"defaultStyle": "default",
"isAnswer": true
}
......@@ -147,19 +135,16 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
},
{
"contentId": 3,
"side": "left",
"defaultStyle": "default",
"isAnswer": true
}
......@@ -168,20 +153,17 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default",
"gotLearningGoalPlaceholder": true
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
},
{
"contentId": 3,
"side": "left",
"defaultStyle": "default",
"isAnswer": true
}
......@@ -190,12 +172,10 @@ let cardTypeCubeSides = [
[
{
"contentId": 2,
"side": "front",
"defaultStyle": "default"
},
{
"contentId": 1,
"side": "back",
"defaultStyle": "default",
"defaultTextAlign": "center",
"isAnswer": true,
......@@ -203,7 +183,6 @@ let cardTypeCubeSides = [
},
{
"contentId": 3,
"side": "left",
"defaultStyle": "default",
"isAnswer": true
}
......@@ -212,33 +191,27 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"defaultTextAlign": "center"
},
{
"contentId": 3,
"side": "left",
"defaultStyle": "default"
},
{
"contentId": 4,
"side": "right",
"defaultStyle": "default"
},
{
"contentId": 5,
"side": "top",
"defaultStyle": "default"
},
{
"contentId": 6,
"side": "bottom",
"defaultStyle": "default"
}
],
......@@ -246,7 +219,6 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "post-it"
}
],
......@@ -254,7 +226,6 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default"
}
],
......@@ -262,12 +233,10 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "white"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "white"
}
],
......@@ -275,12 +244,10 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
......@@ -290,35 +257,29 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default"
},
{
"contentId": 3,
"side": "right",
"defaultStyle": "default"
},
{
"contentId": 4,
"side": "back",
"defaultStyle": "default"
},
{
"contentId": 2,
"side": "left",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
},
{
"contentId": 5,
"side": "top",
"defaultStyle": "default",
"isAnswer": true
},
{
"contentId": 6,
"side": "bottom",
"defaultStyle": "default",
"isAnswer": true
}
......@@ -327,26 +288,22 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default",
"gotLearningGoalPlaceholder": true
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"isAnswer": true
},
{
"contentId": 3,
"side": "left",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
},
{
"contentId": 4,
"side": "right",
"defaultStyle": "default",
"isAnswer": true
}
......@@ -356,7 +313,6 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "white"
}
......@@ -365,13 +321,11 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default",
"gotLearningGoalPlaceholder": true
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
......@@ -381,12 +335,10 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
......@@ -396,12 +348,10 @@ let cardTypeCubeSides = [
[
{
"contentId": 1,
"side": "front",
"defaultStyle": "default"
},
{
"contentId": 2,
"side": "back",
"defaultStyle": "default",
"isAnswer": true,
"isAnswerFocus": true
......
......@@ -15,6 +15,19 @@ let iFrameMaxHeight = 0.8;
//5: Wozniak
let fixedSidebarPosition = [1, 2, 3, 4, 5];
//3D Mode settings
//0: Default (Cardset and other views), Currently not supported
//1: Presentation
//2: Demo / Making Of
//3: Editor
//4: Leitner
//5: Wozniak
let enabled3DModeByDefault = [1, 2, 3, 4, 5];
let got3DMode = [1, 2, 3, 4, 5];
let cubeTransitionTime = 1.5;
let cubeMaxNavigationWidth = 1200;
module.exports = {
defaultFontSize,
defaultFontSizeMobile,
......@@ -22,5 +35,9 @@ module.exports = {
iFrameWidthRatio,
iFrameHeightRatio,
iFrameMaxHeight,
fixedSidebarPosition
fixedSidebarPosition,
enabled3DModeByDefault,
got3DMode,
cubeTransitionTime,
cubeMaxNavigationWidth
};
......@@ -8,9 +8,11 @@ let macOSPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'];
//1: WordCloud - Landing Page
//2: WordCloud - Filter
//3: Demo
//4: 3D-Cube
//5: 3D-Cube: cancel active transitions
let enabledSmartphoneFeatures = [0, 1, 2, 3];
let enabledIOSFeatures = [2, 3];
let enabledMacOSSafariFeatures = [2, 3];
let enabledIOSFeatures = [2, 3, 4];
let enabledMacOSSafariFeatures = [2, 3, 4, 5];
module.exports = {
minimumTabletWidth,
......
......@@ -927,6 +927,14 @@ Template.registerHelper("isSmartphone", function () {
return NavigatorCheck.isSmartphone();
});
Template.registerHelper("is3DActive", function () {
return Session.get('is3DActive');
});
Template.registerHelper("got3DMode", function () {
return CardVisuals.got3DMode();
});
const markdeepHelper = new MeteorMathJax.Helper({
useCache: false,
transform: function (content) {
......
......@@ -12,17 +12,32 @@
{{/unless}}
<div id="cardCarousel" class="carousel slide" data-keyboard="false" data-interval="false">
<div class="carousel-inner">
{{#unless isMobilePreviewActive}}
{{> flashcardSidebar}}
{{/unless}}
{{#each getCards}}
{{> cardSide this}}
{{/each}}
{{#if is3DActive}}
{{> flashcardsCarouselContent3D}}
{{else}}
{{> flashcardsCarouselContent}}
{{/if}}
</div>
</div>
</div>
</template>
<template name="flashcardsCarouselContent">
{{#each getCards}}
{{> cardSide setCardStatus}}
{{/each}}
</template>
<template name="flashcardsCarouselContent3D">
{{#each getCards}}
{{#if isActiveCard}}
{{> cardCube setCardStatus}}
{{else}}
{{> cardSide setCardStatus}}
{{/if}}
{{/each}}
</template>
<template name="flashcardsEmpty">
<div class="card-container">
<div>
......
......@@ -15,8 +15,8 @@ import {Leitner, Wozniak} from "../../api/learned.js";
import {BertAlertVisuals} from "../../api/bertAlertVisuals";
import {CardEditor} from "../../api/cardEditor";
import {TouchNavigation} from "../../api/touchNavigation";
import './header/header.js';
import './content/content.js';
import './side/header/header.js';
import './side/content/content.js';
import './navigation/navigation.js';
import './modal/settings.js';
import "./modal/beolingusTranslation.js";
......@@ -24,8 +24,24 @@ import "./modal/deeplTranslation.js";
import "./modal/deleteCard.js";
import "./modal/copyCard.js";
import './side/side.js';
import './cube/cube.js';
import "./card.html";
function isActiveCard(card, resetData) {
if (Route.isEditMode()) {
return true;
} else {
if (Session.get('activeCard') === card._id) {
if (resetData) {
let cubeSides = CardType.getCardTypeCubeSides(card.cardType);
Session.set('cardType', card.cardType);
Session.set('activeCardContentId', CardType.getActiveSideData(cubeSides, card.cardType));
Session.set('activeCardStyle', CardType.getActiveSideData(cubeSides, card.cardType, 1));
}
return true;
}
}
}