Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger Prod from Feature #73

Closed
wants to merge 206 commits into from
Closed

Trigger Prod from Feature #73

wants to merge 206 commits into from

Conversation

rtshkmr
Copy link
Member

@rtshkmr rtshkmr commented Aug 10, 2024

No description provided.

rtshkmr and others added 30 commits December 5, 2023 00:04
QQ: seems like I can only use buttons to do click events, how might I go
about emitting click events from icons?
Added a /hooks subdir to throw in js-hooks and an indexer file for that.
Just playing around with things...
This gets validated by just observing the html source code.

The next step would be to add in the image generation. For a first pass,
the image generation shall be done just-in-time, will add in some
cacheing thereafter as a v1.
Things added:
1. chapter, verse number
2. both text and transliteration
3. url dump
syncs commits in the prod branch with this feature branch

Co-authored-by: ks0m1c_dharma <[email protected]>
Co-authored-by: ks0m1c_dharma <[email protected]>
Things done:
1. Added a livecomponent which has a div. The div calls a js hook
2. the js hook creates a new script tag which inserts itself as the
first script of the html document.
  * this is the most probable source of error because I think the
  callback functions are not being passed to the correct html element. I
  should explore this when I get back to this problem. The ideal case
  should be how it is shown on the iframe documentation that we see.
3. The cors issues have been resolved by adding the CORS plug that we
saw. This CORS plug allows youtube.com/iframe_api to be a valid source.
This actually works for all browsers.
4. If I embed this script tag directly to the heex template, it will
work. However, it won't work when I'm attempting to create do it via a
JS-Hook. There's a high likelyhood that it's just me being noob at
Elixir/LiveView and that's why I can't get it to work yet.

REF: https://developers.google.com/youtube/iframe_api_reference

Hunch(es):
1. I might have to just insert things into the correct script tag
properly. I had already tried inserting innerthtml but it just got
parsed as a string. Maybe I should relook at that.
2. Kinda related to point 2 above
Co-authored-by: ks0m1c_dharma <[email protected]>
Co-authored-by: ks0m1c_dharma <[email protected]>
Conflicts: (accepted both, HEAD for outdated areas)
assets/js/hooks/index.js
lib/vyasa_web/live/gita_live/show_verse.html.heex
mix.exs
mix.lock
As long as this reference exists, we will be able to invoke JS API calls
that the youtube player exposes.
Currently, I've just supported "seekTo" and "loadVideoById" callbacks.
Got a bunch of video stats that gets spit out onhover of a button.
Built a custom tooltip here.

Key Takeaways:
1. added import to root template. UMD import done as described here [1], other imports won't work well.
2. followed their tutorial on how to setup a custom tooltip, used
show_verse to demonstrate it. Didn't create a generic template /
component for it, but I think this is good enough since it shows an
live-view-integrated version of the floating-ui tutorial as seen here [2]
3. the middleware is just magic.

[1]: https://floating-ui.com/docs/getting-started#umd
[2]: https://floating-ui.com/docs/tutorial
ks0m1c_dharma and others added 25 commits March 16, 2024 22:58
Introduction of Bindings && Cherrywrap Nimble OG Image
Introduction of Bindings && JIT OG Image
* [Refactor]: Use ms as time units

* [Attempt]: player_details -> %Meta{}, use ms

+ The key goals for this commit were:
1. for all the time operations, use milliseconds as units by default
2. instead of using player_details, directly use %Playback{}, any other
meta info can be expliclity defined via the %Meta{} which is a nested
struct within %Playback that is medium-agnostic.

+ The following were done:
1. update %Playback{} to contain an inner struct: %Meta{}
2. Deprecate player_details:
3. Deprecate use of TimeUtils::nowSeconds() ==> nowMs()

- Here are the issues that are yet to be addressed, in order of
importance:
1. TimeCalculation issue.
   Somehow, there's a new bug introduced when doing a progress_bar seek.
   The time calculation done @
   media_bridge.ex::update_playback_on_seek() is causing a crash,
   claiming a pattern mismatch for the inferred arity of 4. Oddly, I'm
   only passing in 3 arguments, so it should be an arity of 3...

2. Seeding issues: after loading events, the voice's embedded meta
attribute is nil ==> ensuring that it's non-nil overlaps with our
MediaSessionsApi task

3. to update attribute name in the voice::meta table column where
"artist" should actually be "artists" since it's an array. Low priority.

4. youtube_player.js:: is receiving %Playback{} but it's not using the
info within it. Maybe using the elapsed value here might improve the
audio-video sync.

* Fix time calculation issue by rounding ms

The learning here was that the calculation was failing when the ms value
was a non-integer.

The fix was to just make it an int.

Also learnt that for DateTime, there's two "formats":
1. ~U ==> which includes timezone info
2. ~N ==> which is the naive datetime, does not include timezone info

2 works well because it's backwards compatible, can consider using 2 by default.
Key Learnings:
1. crash was happening because of a known case encountered before: remember to use integers for DateTime.add()

2. As for the dom issues, using the browser's debugger showed that when using a watch expression for the style state, it would go out of scope (implying a re-render). Hence the realisation that it's a matter of ignoring the dom-patching by LiveView. Based on the documentation for it [^1], it seems that ignoring dom-patching should be considered whenever we use JS-hooks to programmatically manipulate the state.

[^1]: https://hexdocs.pm/phoenix_live_view/dom-patching.html
This is just to prevent the compilation warning.
* Add voices gen_changeset & update migration docs

* Update README, add wow.json

* Init ox-hugo for writing setup

* Create CNAME

* Delete CNAME

* Create CNAME

* Init workflow

* Update workflow file

* Rm erroneous working dir

* Re-init submodule for theme

* Add some basic routes

* Make refs use https://

It's an attempt to prevent mixed use of http and https://
## Overview

This PR does a bunch of things: 
1. refactor of events bridge 
2. use media sessions api


## Migration Notes:
- most recent db state dump (for migration):
[1723306013568018000.json](https://github.com/user-attachments/files/16570171/1723306013568018000.json)


## Commit Descriptions:


* Cleanups: rm old .livemds

* Update migrator script's save() to preload video

* fix imprt stmt & add guard to hoverrune

* Wire up voice metadata

note: because of this, the PR requires the deployment to use a fresh json file

this prepares for the info needed by media sessions

does some linting using the latest elixir-ls

* Use og image for artwork

Not sure why it doesn't display when using the emulator.
I think it's better if I test it on the deployed version directly, not
sure if the testing method is accurate.

* Minor cleanups

* Meta cleanup encode

* Add comma

* Simple changes

* Revert use of Map.from_struct

* Shift guarding to playback.ex instead of encoder

* Add nil clause for meta::Jason encode()

* @derive

* except artwork

* Handle nil case for artwork better w better guard

* Minor changes

* Use dummy metadata example

* Revert dummy example

* iAnother dummy attempt

* Another attempt

* test dict creation

* test use of extra key in media metadata

* Test: use geenrated artwork

* minor change

* Change MIME type for generated_artwork jpeg -> png

* Minor change

* Use createMediaMetadataPayload()

* Server Logging to Console & Image Lib Update

* Init media session @ metadata load

Init functions don't have action handlers yet

* Guard against null playback

* Shift mediaSession update to before play

* Attempt earlier update of metadata

* Use waiting spinner to prevent early play triggers

* Trigger diffs to create draft PR

* Clean up fns on media_bridge.ex

mainly consolidates the functions used for updating playback and
notifying the audio player

* Shift JS event dispatch to AudioPlayer livecomp

Separates the concerns b/w the MediaBridge (generic) and the
AudioPlayer (concrete)

* Shift generic hook event dispatch to media_bridge

* Minor cleanups on MediaBridge hook

* Refactor event handlers within MediaBridgeHook

* Cleanup some handshakes, msg passing

* Fix: disregard duplicate voice_acks

* Add playbackMetaBridge, loadAudio @ earliest time

Change list:

1. reorganise bridges into hooks/mediaEventBridges, within it there's a
new playbackMetaBridge. Intent is to comms playback info and separate
actions from playback info things.

2. now, when the server does a push_event for the audio events
registration, we also send a separate event that is using this new
bridge ("media_bridge:registerPlayback"), which dispatches the necessary
client side events to register the playback, load the audio and the
mediaSession as early as possible. Previously, this used to happen JIT,
when the user was to press the play/pause button. This seems to have
removed the initial time-delay we used to have between the instance when
user clicks "play" and actual playback starting.

3. naturally, we also prevent redundant re-loads of audio now by
guarding the source-setting for the html5 audio player.

Broad TODOs:
1. consider pushing to the new playbackMetaBridge in the same intervals
as the existing heartbeat.

2. this commit only added in message-passing from MediaBridgeHook to the
AudioPlayerHook, but not in the other direction.

* Rm props-passing of playback via <audio/>

Playback state is init @ point of events registration, via a new bridge now.

* Wire up PlayPause Action handlers for MediaSession

Automagically works == pat on the back for good design?

* Rm ack_val passing, implicitly get from the struct

* Cleanup: rm useless event handlers for audioplayer

* Cleanup: rm console.logs from hooks

* Cleanups: minor cleanups on server components

* minor changes

---------

Co-authored-by: ks0m1c_dharma <[email protected]>
@rtshkmr rtshkmr self-assigned this Aug 10, 2024
* [WIP]: basic DM, demo state & assigned components

Still have no idea how the VyasaWeb.SourceLive.Chapter.Index is supposed
to be rendered as @inner_content within the new
display_manager.html.heex

* Rename CommandGroup -> ControlPanel

* Initial Wire up %UserMode{} to Control Panel

* Switch modes, add user_mode.ex to tw config

* Prevent full page-reloads via push_navigate()

This prevents the socket from being killed at every navigation, so the
overlay's states is still managed without any issue.

Actually, currently, there's a issue with definitions on the router-side

problem: if I do a push_navigate to the path matching =/explore/:source_title/:chap_no= from =/explore/:source_title/=,
it will trigger a socket error:
=phx-F-vfg0fv3-NR4yFB error: unauthorized live_redirect. Falling back to page request -=

Hunch: it's because of the router defining two different live_session scopes (anon vs sangh) so it's
not allowing a =push_navigate()= and hence it's reverting to a full page reload.

Do you know a quick fix to this?

    live_session :gen_anon_session,
      on_mount: [{VyasaWeb.Session, :anon}] do
      live "/explore/", SourceLive.Index, :index
      live "/explore/:source_title/", SourceLive.Show, :show
      #live "/explore/:source_title/:chap_no", SourceLive.Chapter.Index, :index
      live "/explore/:source_title/:chap_no", SourceLive.Chapter.Index, :index
      live "/explore/:source_title/:chap_no/:verse_no", SourceLive.Chapter.ShowVerse, :show
    end

    live_session :gen_sangh_session,
      on_mount: [{VyasaWeb.Session, :sangh}] do
        live "/explore/:source_title/:chap_no", SourceLive.Chapter.Index, :index
      end

* [temp] shift all from anon session to sangh sess

* Minor changes

* [WIP, Attempt] Shift from layout to heex template

Still the thing dies on me
basically took the whole day, a bunch of refactoring has happened 

# How to Verify / Test

1. navigate through the thing, if you change the mode then navigate into other parts of the content (e.g. :show_sources -> :show_chapters -> :show_verses) then the ControlPanel mode should be the same, no dismount and remounting or anything either

2. handshake gets done properly. The handshake will init when you're in the :show_verses content view and only then does the audio load. Note that once the audio is loaded, any content navigation will never kill the audio playback either. In fact the audio playback will continue and scribing and all that fun stuff will still happen


# Workplan Notes

```
***** Approach 2: ContentLiveview
:LOGBOOK:
CLOCK: [2024-08-16 Fri 08:39]--[2024-08-16 Fri 17:39] =>  9:00
:END:
****** Test:
1. navigate through content without overlay states being affected
****** 0. Redefine Router, let everything point to DM
****** 1. Add content liveview
- all 3 added
- [LOW IMPORTANCE]

  TOVERIFY: seems like it's correct to preload the stream content @ the liveview then pass it onto a live_component? ([[https://elixirforum.com/t/how-to-use-phoenix-1-7-streams-on-livecomponent-preload/54454][ref]])
  my own implementations:

  PRELOAD @
  #+begin_src elixir
# preload @ display_manager/display_live
  defp apply_action(
         %Socket{} = socket,
         :show_chapters,
         %{"source_title" => source_title} =
           params
       ) do

    [%Chapter{source: src} | _] = chapters = Written.get_chapters_by_src(source_title)
    socket
    |> assign(:content_action, :show_chapters)
    |> assign(:page_title, to_title_case(src.title))
    |> assign(:source, src)
    |> assign(:meta, %{
      title: to_title_case(src.title),
      description: "Explore the #{to_title_case(src.title)}",
      type: "website",
      image: url(~p"/og/#{VyasaWeb.OgImageController.get_by_binding(%{source: src})}"),
      url: url(socket, ~p"/explore/#{src.title}")
    })
    |> stream_configure(:chapters, dom_id: &"Chapter-#{&1.no}")
    |> stream(:chapters, chapters |> Enum.sort_by(fn chap -> chap.no end))
  end
  #+end_src

  INJECT INTO LIVE_COMPONENT:

  #+begin_src elixir
<%= if @content_action == :show_chapters do%>
    <div>
        SHOW CHAPTERS
   <.live_component
      module={VyasaWeb.Content.Chapters}
      id={"content-sources"}
      source={@source}
      chapters={@streams.chapters}
      />
    </div>
<% end %>
  #+end_src

****** 2. defdelegate or add contentFetcher to separate out the repo logic
SKIPPED this, not too important
****** 3. test the push_patch() for this
WORKSSSS

```




---- 


* [WIP]: basic DM, demo state & assigned components

Still have no idea how the VyasaWeb.SourceLive.Chapter.Index is supposed
to be rendered as @inner_content within the new
display_manager.html.heex

* Rename CommandGroup -> ControlPanel

* Initial Wire up %UserMode{} to Control Panel

* Switch modes, add user_mode.ex to tw config

* Prevent full page-reloads via push_navigate()

This prevents the socket from being killed at every navigation, so the
overlay's states is still managed without any issue.

Actually, currently, there's a issue with definitions on the router-side

problem: if I do a push_navigate to the path matching =/explore/:source_title/:chap_no= from =/explore/:source_title/=,
it will trigger a socket error:
=phx-F-vfg0fv3-NR4yFB error: unauthorized live_redirect. Falling back to page request -=

Hunch: it's because of the router defining two different live_session scopes (anon vs sangh) so it's
not allowing a =push_navigate()= and hence it's reverting to a full page reload.

Do you know a quick fix to this?

    live_session :gen_anon_session,
      on_mount: [{VyasaWeb.Session, :anon}] do
      live "/explore/", SourceLive.Index, :index
      live "/explore/:source_title/", SourceLive.Show, :show
      #live "/explore/:source_title/:chap_no", SourceLive.Chapter.Index, :index
      live "/explore/:source_title/:chap_no", SourceLive.Chapter.Index, :index
      live "/explore/:source_title/:chap_no/:verse_no", SourceLive.Chapter.ShowVerse, :show
    end

    live_session :gen_sangh_session,
      on_mount: [{VyasaWeb.Session, :sangh}] do
        live "/explore/:source_title/:chap_no", SourceLive.Chapter.Index, :index
      end

* [temp] shift all from anon session to sangh sess

* Minor changes

* [WIP, Attempt] Shift from layout to heex template

Still the thing dies on me

* Trigger DIFF

* Use DM @ router actions, load data :show_sources

* Add data load for :show_chapters action on DM

* Use push_patch() @ :show_sources -> :show_chapters

* Handle data load & nav:show_chapters->:show_verses

* Create VyasaWeb.Content.Verses live_component

* Wire up handshakes successfully, shift to patches

Also done:
1. use maybe_stream_configure/3 (see note in definition)
2. change backlinks from navigate -> patch so that a full-page reload is
NOT done. This is also what allows the state of ControlPanel and
ActionBar to be maintained despite going back and forth content.
3. actually wiring up the event handlers and stuff that allowed the
handshakes to happen

TODOs:
1. fix css nonsense with how the content is being displayed.
2. future iteration needs a cleanup, this module is too fat.

* Fix css issues

* More minor css fixes
@rtshkmr
Copy link
Member Author

rtshkmr commented Aug 19, 2024

killing this, hanuman was doing too much carrying

image

@rtshkmr rtshkmr closed this Aug 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants