App like TikTok?

Hey

I would like to know if we can create an app on glide like TikTok ? If the user can upload his own videos on the application to the feed ?

Tnks a lot for you help guys ! :wink:

Thomas

You can do that with the file picker component, but users will still have to go into the details of each item to view the video.

1 Like

Alright thanks @ThinhDinh :handshake:

1 Like

You can’t scroll it though, you need a concept like THIS (I made this cause I got the same problem)

What should the next button do? Shuffle order doesn’t work.

hi @Ashton_Pelzel , if you want, you can try this JS code from @Himaladin to display a list of videos.

function createYouTubePlayer(p1, p2) {
  let titles = p1.split(',');
  let videoUrls = p2.split(',');

  if (titles.length !== videoUrls.length) {
    return 'Invalid YouTube Playlist';
  }

  let playlist = titles.map((title, index) => {
    let videoUrl = videoUrls[index];
    let videoId = getVideoIdFromUrl(videoUrl);
    return { id: videoId, url: videoUrl, title: title };
  });

  function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
  }

  shuffleArray(playlist);

  let firstVideoId = playlist[0].id;

  let html = `
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>YouTube Playlist Player</title>
  <style>
body {
display: flex;
flex-direction: column;
background-color: transparent !important;
font-family: Arial, sans-serif;
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
}
    .player-container {
      position: relative;
      width: 100%;
      padding-top: 56.25%; /* 16:9 ratio */
      margin-bottom: 20px;
    }
    #player {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      border-radius: 8px;
    }
    .sticky-header {
      color: white;
    }
    .table-container {
      width: 100%;
      margin-bottom: 20px;
      overflow-y: auto;
    }
    table {
      width: 100%;
      border-collapse: collapse;
      color: #777777;
text-shadow: 0.5px 0px 0px rgba(0, 0, 0, 1);
      table-layout: fixed;
    }
    table th:nth-child(1),
    table td:nth-child(1) {
      width: 55px;
    }
    td {
      padding: 10px;
      text-align: left;
      vertical-align: top;
      border-bottom: 1px solid #333333;
    }
    .now-playing {
      background-color: rgba(100, 100, 100, 0.2);
    }
    tr:hover {
      background-color: #B80F0F;
      color: #fff;
      cursor: pointer;
    }

    .button-container {
      display: flex;
      justify-content: flex-start;
      margin-bottom: 20px;
    }
    .button-container button {
      background-color: #555555;
      color: white;
      border: none;
      padding: 5px 10px;
      margin: 0 5px;
      border-radius: 5px;
      cursor: pointer;
      transition: background-color 0.3s ease;
    }
    .button-container button.active {
      background-color: #B80F0F;
    }
  </style>
</head>
<body>
  <div class="player-container">
    <div id="player"></div>
  </div>
  <h4 class="sticky-header">Playlist Videos</h4>
  <div class="button-container">
    <button id="shuffleButton" onclick="shufflePlaylist()" class="active">Shuffle</button>
    <button id="sortButton" onclick="sortPlaylist()">Sort</button>
  </div>
  <div class="table-container">
    <table>
      <tbody id="playlistTable">
        ${playlist.map((item, index) => `
          <tr id="video-${item.id}" onclick="playVideo('${item.id}', '${item.url}')" class="${index === 0 ? 'now-playing' : ''}">
            <td>${index + 1}</td>
            <td>${item.title}</td>
          </tr>
        `).join('')}
      </tbody>
    </table>
  </div>
  <script>
    var player;
    var currentIndex = 0;
    var originalPlaylist = ${JSON.stringify(playlist)};
    var playlist = ${JSON.stringify(playlist)};

    function onYouTubeIframeAPIReady() {
      player = new YT.Player('player', {
        videoId: '${firstVideoId}',
        playerVars: {
          'controls': 1,
          'showinfo': 0,
          'rel': 0,
          'modestbranding': 1,
          'listType': 'playlist'
        },
        events: {
          'onReady': onPlayerReady,
          'onStateChange': onPlayerStateChange
        }
      });
    }

    function onPlayerReady(event) {
      event.target.playVideo();
    }

    function onPlayerStateChange(event) {
      if (event.data == YT.PlayerState.ENDED) {
        if (currentIndex < playlist.length - 1) {
          currentIndex++;
          var nextVideoId = playlist[currentIndex].id;
          player.loadVideoById(nextVideoId);
          player.playVideo();
          updateNowPlayingStyle(nextVideoId);
        }
      }
    }

    function playVideo(videoId, videoUrl) {
      currentIndex = playlist.findIndex(item => item.id === videoId);
      if (currentIndex !== -1) {
        player.loadVideoById(videoId);
        player.playVideo();
        updateNowPlayingStyle(videoId);
      }
    }

    function updateNowPlayingStyle(videoId) {
      document.querySelectorAll('tr').forEach(item => {
        item.classList.remove('now-playing');
      });
      document.getElementById('video-' + videoId).classList.add('now-playing');
    }

    function shufflePlaylist() {
      shuffleArray(playlist);
      currentIndex = 0;
      updatePlaylistButtons(true);
      playVideo(playlist[currentIndex].id, playlist[currentIndex].url);
    }

    function sortPlaylist() {
      playlist = [...originalPlaylist];
      currentIndex = 0;
      updatePlaylistButtons(false);
      playVideo(playlist[currentIndex].id, playlist[currentIndex].url);
    }

    function shuffleArray(array) {
      for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
    }

    function updatePlaylistButtons(isShuffle) {
      document.getElementById('shuffleButton').classList.toggle('active', isShuffle);
      document.getElementById('sortButton').classList.toggle('active', !isShuffle);
    }

  </script>
  <script src="https://www.youtube.com/iframe_api"></script>
</body>
</html>
`;

  let uri = 'data:text/html;charset=utf-8,' + encodeURIComponent(html);
  return uri;
}

function getVideoIdFromUrl(url) {
  var regExp = /^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/;
  var match = url.match(regExp);

  if (match && match[1]) {
    return match[1];
  } else {
    return null;
  }
}

return createYouTubePlayer(p1, p2);

You will need 3 columns like this:

Note that the video links and video titles should occur in the same order, comma separated.

The result looks like this:

1 Like

Thanks, but I already gave up on that. I’ll try though!

1 Like