From fab0c5a77a01389e8f215a78afb2306ad8eaacbf Mon Sep 17 00:00:00 2001 From: Daan Vanden Bosch Date: Fri, 17 Sep 2021 16:05:55 +0200 Subject: [PATCH] Using fontawesome JS SVG core API instead of simple API. --- .../world/phantasmal/core/unsafe/UnsafeMap.kt | 11 ++++ webui/build.gradle.kts | 5 +- .../kotlin/world/phantasmal/webui/dom/Dom.kt | 58 +++++++++++-------- .../fontawesome/fontawesomeSvgCore.kt | 22 +++++++ .../fontawesomeFreeSolidSvgIcons.kt | 8 +++ .../fontawesomeFreeSolidSvgIcons.kt | 9 +++ .../fontawesomeFreeSolidSvgIcons.kt | 23 ++++++++ .../world/phantasmal/webui/widgets/Widget.kt | 7 --- 8 files changed, 112 insertions(+), 31 deletions(-) create mode 100644 webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/fontawesomeSvgCore.kt create mode 100644 webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeBrandsSvgIcons/fontawesomeFreeSolidSvgIcons.kt create mode 100644 webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeRegularSvgIcons/fontawesomeFreeSolidSvgIcons.kt create mode 100644 webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeSolidSvgIcons/fontawesomeFreeSolidSvgIcons.kt diff --git a/core/src/commonMain/kotlin/world/phantasmal/core/unsafe/UnsafeMap.kt b/core/src/commonMain/kotlin/world/phantasmal/core/unsafe/UnsafeMap.kt index ae5c169b..fbad183e 100644 --- a/core/src/commonMain/kotlin/world/phantasmal/core/unsafe/UnsafeMap.kt +++ b/core/src/commonMain/kotlin/world/phantasmal/core/unsafe/UnsafeMap.kt @@ -12,3 +12,14 @@ expect class UnsafeMap() { fun set(key: K, value: V) fun delete(key: K): Boolean } + +fun UnsafeMap.getOrPut(key: K, default: () -> V): V { + var value = get(key) + + if (value == null) { + value = default() + set(key, value) + } + + return value +} diff --git a/webui/build.gradle.kts b/webui/build.gradle.kts index 55096a4a..8f9bb36f 100644 --- a/webui/build.gradle.kts +++ b/webui/build.gradle.kts @@ -5,7 +5,10 @@ plugins { dependencies { api(project(":core")) api(project(":observable")) - implementation(npm("@fortawesome/fontawesome-free", "^5.13.1")) + implementation(npm("@fortawesome/fontawesome-svg-core", "^1.2.36")) + implementation(npm("@fortawesome/free-regular-svg-icons", "^5.15.4")) + implementation(npm("@fortawesome/free-solid-svg-icons", "^5.15.4")) + implementation(npm("@fortawesome/free-brands-svg-icons", "^5.15.4")) testImplementation(project(":test-utils")) } diff --git a/webui/src/main/kotlin/world/phantasmal/webui/dom/Dom.kt b/webui/src/main/kotlin/world/phantasmal/webui/dom/Dom.kt index eaf3216e..95081fa4 100644 --- a/webui/src/main/kotlin/world/phantasmal/webui/dom/Dom.kt +++ b/webui/src/main/kotlin/world/phantasmal/webui/dom/Dom.kt @@ -10,10 +10,18 @@ import org.w3c.dom.pointerevents.PointerEvent import world.phantasmal.core.disposable.Disposable import world.phantasmal.core.disposable.Disposer import world.phantasmal.core.disposable.disposable +import world.phantasmal.core.unsafe.UnsafeMap +import world.phantasmal.core.unsafe.getOrPut import world.phantasmal.observable.cell.Cell import world.phantasmal.observable.cell.list.ListCell import world.phantasmal.observable.cell.list.ListChange import world.phantasmal.observable.cell.list.ListChangeEvent +import world.phantasmal.webui.externals.fontawesome.IconDefinition +import world.phantasmal.webui.externals.fontawesome.freeBrandsSvgIcons.faGithub +import world.phantasmal.webui.externals.fontawesome.freeRegularSvgIcons.faCaretSquareRight +import world.phantasmal.webui.externals.fontawesome.freeRegularSvgIcons.faEye +import world.phantasmal.webui.externals.fontawesome.freeSolidSvgIcons.* +import world.phantasmal.webui.externals.fontawesome.icon as faIcon fun EventTarget.disposableListener( type: String, @@ -120,32 +128,36 @@ enum class Icon { Undo, } +/** Fontawesome icons. */ +private val faElementCache = UnsafeMap() + fun Node.icon(icon: Icon): HTMLElement { - val iconStr = when (icon) { - Icon.ArrowDown -> "fas fa-arrow-down" - Icon.ArrowRight -> "fas fa-arrow-right" - Icon.Eye -> "far fa-eye" - Icon.File -> "fas fa-file" - Icon.GitHub -> "fab fa-github" - Icon.LevelDown -> "fas fa-level-down-alt" - Icon.LevelUp -> "fas fa-level-up-alt" - Icon.LongArrowRight -> "fas fa-long-arrow-alt-right" - Icon.NewFile -> "fas fa-file-medical" - Icon.Play -> "fas fa-play" - Icon.Plus -> "fas fa-plus" - Icon.Redo -> "fas fa-redo" - Icon.Remove -> "fas fa-trash-alt" - Icon.Save -> "fas fa-save" - Icon.Stop -> "fas fa-stop" - Icon.SquareArrowRight -> "far fa-caret-square-right" - Icon.TriangleDown -> "fas fa-caret-down" - Icon.TriangleUp -> "fas fa-caret-up" - Icon.Undo -> "fas fa-undo" + val iconDef = when (icon) { + Icon.ArrowDown -> faArrowDown + Icon.ArrowRight -> faArrowRight + Icon.Eye -> faEye + Icon.File -> faFile + Icon.GitHub -> faGithub + Icon.LevelDown -> faLevelDownAlt + Icon.LevelUp -> faLevelUpAlt + Icon.LongArrowRight -> faLongArrowAltRight + Icon.NewFile -> faFileMedical + Icon.Play -> faPlay + Icon.Plus -> faPlus + Icon.Redo -> faRedo + Icon.Remove -> faTrashAlt + Icon.Save -> faSave + Icon.Stop -> faStop + Icon.SquareArrowRight -> faCaretSquareRight + Icon.TriangleDown -> faCaretDown + Icon.TriangleUp -> faCaretUp + Icon.Undo -> faUndo } - // Wrap the span in another span, because Font Awesome will replace the inner element. This way - // the returned element will stay valid. - return span { span { className = iconStr } } + return span { + val iconEl = faElementCache.getOrPut(iconDef) { faIcon(iconDef).node[0]!! } + append(iconEl.cloneNode(deep = true)) + } } fun bindChildrenTo( diff --git a/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/fontawesomeSvgCore.kt b/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/fontawesomeSvgCore.kt new file mode 100644 index 00000000..26e5fa09 --- /dev/null +++ b/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/fontawesomeSvgCore.kt @@ -0,0 +1,22 @@ +@file:JsModule("@fortawesome/fontawesome-svg-core") +@file:JsNonModule + +package world.phantasmal.webui.externals.fontawesome + +import org.w3c.dom.HTMLCollection + +external class IconDefinition + +external class Icon { + val html: Array + val node: HTMLCollection +} + +external fun icon(icon: IconDefinition): Icon + +external class Config { + /** async or sync */ + var mutateApproach: String +} + +external val config: Config diff --git a/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeBrandsSvgIcons/fontawesomeFreeSolidSvgIcons.kt b/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeBrandsSvgIcons/fontawesomeFreeSolidSvgIcons.kt new file mode 100644 index 00000000..bc4ca87c --- /dev/null +++ b/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeBrandsSvgIcons/fontawesomeFreeSolidSvgIcons.kt @@ -0,0 +1,8 @@ +@file:JsModule("@fortawesome/free-brands-svg-icons") +@file:JsNonModule + +package world.phantasmal.webui.externals.fontawesome.freeBrandsSvgIcons + +import world.phantasmal.webui.externals.fontawesome.IconDefinition + +external val faGithub: IconDefinition diff --git a/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeRegularSvgIcons/fontawesomeFreeSolidSvgIcons.kt b/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeRegularSvgIcons/fontawesomeFreeSolidSvgIcons.kt new file mode 100644 index 00000000..6debd914 --- /dev/null +++ b/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeRegularSvgIcons/fontawesomeFreeSolidSvgIcons.kt @@ -0,0 +1,9 @@ +@file:JsModule("@fortawesome/free-regular-svg-icons") +@file:JsNonModule + +package world.phantasmal.webui.externals.fontawesome.freeRegularSvgIcons + +import world.phantasmal.webui.externals.fontawesome.IconDefinition + +external val faCaretSquareRight: IconDefinition +external val faEye: IconDefinition diff --git a/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeSolidSvgIcons/fontawesomeFreeSolidSvgIcons.kt b/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeSolidSvgIcons/fontawesomeFreeSolidSvgIcons.kt new file mode 100644 index 00000000..fd93bdc3 --- /dev/null +++ b/webui/src/main/kotlin/world/phantasmal/webui/externals/fontawesome/freeSolidSvgIcons/fontawesomeFreeSolidSvgIcons.kt @@ -0,0 +1,23 @@ +@file:JsModule("@fortawesome/free-solid-svg-icons") +@file:JsNonModule + +package world.phantasmal.webui.externals.fontawesome.freeSolidSvgIcons + +import world.phantasmal.webui.externals.fontawesome.IconDefinition + +external val faArrowDown: IconDefinition +external val faArrowRight: IconDefinition +external val faCaretDown: IconDefinition +external val faCaretUp: IconDefinition +external val faFile: IconDefinition +external val faFileMedical: IconDefinition +external val faLevelDownAlt: IconDefinition +external val faLevelUpAlt: IconDefinition +external val faLongArrowAltRight: IconDefinition +external val faPlay: IconDefinition +external val faPlus: IconDefinition +external val faRedo: IconDefinition +external val faSave: IconDefinition +external val faStop: IconDefinition +external val faTrashAlt: IconDefinition +external val faUndo: IconDefinition diff --git a/webui/src/main/kotlin/world/phantasmal/webui/widgets/Widget.kt b/webui/src/main/kotlin/world/phantasmal/webui/widgets/Widget.kt index f439af99..f82b319a 100644 --- a/webui/src/main/kotlin/world/phantasmal/webui/widgets/Widget.kt +++ b/webui/src/main/kotlin/world/phantasmal/webui/widgets/Widget.kt @@ -217,13 +217,6 @@ abstract class Widget( el } - init { - js("require('@fortawesome/fontawesome-free/js/fontawesome');") - js("require('@fortawesome/fontawesome-free/js/solid');") - js("require('@fortawesome/fontawesome-free/js/regular');") - js("require('@fortawesome/fontawesome-free/js/brands');") - } - protected fun style(style: String) { STYLE_EL.append(style) }