Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
farism committed Sep 11, 2023
0 parents commit 8dea166
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI

on:
push:
branches:
- main
tags:
- "*"

pull_request:
branches:
- main

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- name: Download source
uses: actions/checkout@v2

- name: Install Mint
uses: fabasoad/setup-mint-action@main
with:
version: 0.18.0

- name: Install dependencies
run: mint install

- name: Run tests
run: mint test
9 changes: 9 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
MIT License

Copyright 2023 Faris Mustafa

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Mint Fullscreen

[![CI](https://github.com/farism/mint-fullscreen/actions/workflows/ci.yml/badge.svg)](https://github.com/farism/mint-battery/actions/workflows/ci.yml)

[Mint](https://mint-lang.com/) wrapper for the browser [Fullscreen API](https://developer.mozilla.org/docs/Web/API/Fullscreen_API)

# `Example`

Example of using the `Fullscreen` module

```mint
component Main {
fun enter {
case target {
Maybe::Just(el) =>
{
Fullscreen.enter(el)
void
}
=> void
}
}
fun exit {
Fullscreen.exit()
}
fun render {
<div as target>
<button onClick={enter}>
"enter fullscreen"
</button>
<button onClick={exit}>
"exit fullscreen"
</button>
</div>
}
}
```

# `Functions`

The `Fullscreen` module

- `enter(el : Dom.Element)` - Requests to enter fullscreen mode

- `exit()` - Requests to leave fullscreen mode

- `element() : Maybe(Dom.Element)` - Returns the active fullscreen element

- `isAvailable() : Bool` - Is the Fullscreen API available to use in the browser

- `isActive() : Bool` - Is fullscreen mode currently activated on an element
9 changes: 9 additions & 0 deletions mint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "mint-fullscreen",
"source-directories": [
"source"
],
"test-directories": [
"tests"
]
}
84 changes: 84 additions & 0 deletions source/Fullscreen.mint
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
enum Fullscreen.NavigationUi {
/* The browser will choose which of the above settings to apply. This is the default value. */
Auto

/* The browser's navigation interface will be hidden and the entire dimensions of the screen will be allocated to the display of the element. */
Hide

/* The browser will present page navigation controls and possibly other user interface; the dimensions of the element (and the perceived size of the screen) will be clamped to leave room for this user interface. */
Show
}

record Fullscreen.Options {
navigationUi : Fullscreen.NavigationUi
}



module Fullscreen {
/* Tells you the Element that's currently being displayed in fullscreen mode on the DOM (or shadow DOM). If this `is Maybe::Nothing`, the document (or shadow DOM) is not in fullscreen mode. */
fun element : Maybe(Dom.Element) {
`
(() => {
const el = document.fullscreenElement

return el
? #{Maybe::Just(`el`)}
: #{Maybe::Nothing}
})()
`
}

/*
Issues an asynchronous request to make the element be displayed in fullscreen mode.
It's not guaranteed that the element will be put into full screen mode. If permission to enter full screen mode is granted, the returned Promise will resolve and the element will receive a fullscreenchange event to let it know that it's now in full screen mode. If permission is denied, the promise is rejected and the element receives a fullscreenerror event instead. If the element has been detached from the original document, then the document receives these events instead.
*/
fun enter (
element : Dom.Element,
options : Fullscreen.Options = { navigationUi: Fullscreen.NavigationUi::Auto }
) : Promise(Result(String, Void)) {
`
(() => {
const opts = {
navigationUI: #{navigationUiToString(options.navigationUi)}
}

return #{element}
.requestFullscreen()
.then(() => #{Result::Ok(void)})
.catch((e) => #{Result::Err(`e.message`)})
})()
`
}

/* Requests that the element on this document which is currently being presented in fullscreen mode be taken out of fullscreen mode, restoring the previous state of the screen. This usually reverses the effects of a previous call to `Fullscreen.enter`. */
fun exit : Promise(Result(String, Void)) {
`
(() => {
return document
.exitFullscreen()
.then(() => #{Result::Ok(void)})
.catch((e) => #{Result::Err(`e.message`)})
})()
`
}

/* Tells you whether or not fullscreen mode is currently activated */
fun isActive : Bool {
element() != Maybe::Nothing
}

/* Tells you whether or not it is possible to engage fullscreen mode. This is false if fullscreen mode is not available for any reason (such as the "fullscreen" feature not being allowed, or fullscreen mode not being supported). */
fun isAvailable : Bool {
`document.fullscreenEnabled`
}

fun navigationUiToString (navigationUi : Fullscreen.NavigationUi) : String {
case navigationUi {
Fullscreen.NavigationUi::Auto => "auto"
Fullscreen.NavigationUi::Hide => "hide"
Fullscreen.NavigationUi::Show => "show"
}
}
}
93 changes: 93 additions & 0 deletions tests/Fullscreen.mint
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
component Test.Fullscreen {
state enterResult : String = ""
state exitResult : String = ""

fun enter {
let res =
await case el {
Maybe::Just(el) =>
case await Fullscreen.enter(el) {
Result::Err(err) => err
=> ""
}

=> Promise.resolve("")
}

next { enterResult: res }
}

fun exit {
let res =
await case el {
Maybe::Just(el) =>
case await Fullscreen.exit() {
Result::Err(err) => err
=> ""
}

=> Promise.resolve("")
}

next { exitResult: res }
}

fun render : Html {
<div as el>
<btn
id="enter"
onClick={enter}/>

<btn
id="exit"
onClick={exit}/>

<enterresult>
<{ enterResult }>
</enterresult>

<exitresult>
<{ exitResult }>
</exitresult>
</div>
}
}

suite "Fullscreen" {
test "element()" {
Test.Context.of(Fullscreen.element())
|> Test.Context.assertEqual(Maybe::Nothing)
}

test "isAvailable()" {
Test.Context.of(Fullscreen.isAvailable())
|> Test.Context.assertEqual(true)
}

// this test breaks for some reason. if using `true` for assert value it passes

// test "isActive()" {

// Test.Context.of(Fullscreen.isActive())

// |> Test.Context.assertEqual(false)

// }
test "isActive()" {
Fullscreen.isActive() == false
}

test "enter()" {
<Test.Fullscreen/>
|> Test.Html.start()
|> Test.Html.triggerClick("#enter")
|> Test.Html.assertTextOf("enterresult", "Permissions check failed")
|> Test.Html.triggerClick("#exit")
|> Test.Html.assertTextOf("exitresult", "Failed to execute 'exitFullscreen' on 'Document': Document not active")
}

test "exit()" {
<Test.Fullscreen/>
|> Test.Html.start()
}
}

0 comments on commit 8dea166

Please sign in to comment.