PlaylistExportDialog.razor 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. @inherits FnzComponentBase
  2. @code {
  3. private FnzBootstrapModal mdl;
  4. private Guid PlaylistId { get; set; }
  5. private string ExportName { get; set; } = "brrr";
  6. private bool ExportDomainCheck { get; set; } = true;
  7. private string ExportDomain { get; set; } = "brrr";
  8. private bool ExportDateCheck { get; set; } = true;
  9. private string ExportDate { get; set; } = "brrr";
  10. private string ExportExtension { get; set; } = "brrr";
  11. private int ExportCodePage { get; set; } = 0;
  12. private string ExportMime { get; set; } = "brrrr";
  13. private string _exportDataUri = null;
  14. private string _exportFileName = null;
  15. }
  16. @code{
  17. protected override void OnInitialized()
  18. {
  19. base.OnInitialized();
  20. }
  21. }
  22. <FnzBootstrapModal @ref="mdl">
  23. <Title>Export playlist</Title>
  24. <Body>
  25. <div class="input-group mb-3">
  26. <span class="input-group-text">File Name</span>
  27. <InputText class="form-control" placeholder="Filename"
  28. Value="@ExportName"
  29. ValueExpression="()=>ExportName"
  30. ValueChanged="s=>ExportName=s"></InputText>
  31. </div>
  32. <div class="input-group mb-3">
  33. <div class="input-group-text">
  34. <label>
  35. <input class="form-check-input mt-0 align-middle" type="checkbox" checked="@ExportDomainCheck" @bind-value="ExportDomainCheck">
  36. <span class="align-middle">-Host</span>
  37. </label>
  38. </div>
  39. <InputText class="form-control"
  40. Value="@ExportDomain"
  41. ValueExpression="()=>ExportDomain"
  42. ValueChanged="s=>ExportDomain=s"></InputText>
  43. </div>
  44. <div class="input-group mb-3">
  45. <div class="input-group-text">
  46. <label>
  47. <input class="form-check-input mt-0 align-middle" type="checkbox" checked="@ExportDateCheck" @bind-value="ExportDateCheck">
  48. <span class="align-middle">-Date</span>
  49. </label>
  50. </div>
  51. <InputText class="form-control"
  52. Value="@ExportDate"
  53. ValueExpression="()=>ExportDate"
  54. ValueChanged="s=>ExportDate=s"></InputText>
  55. </div>
  56. <div class="input-group mb-3">
  57. <span class="input-group-text">Text Encoding</span>
  58. <InputSelect class="form-control" TValue="int"
  59. Value="ExportCodePage"
  60. ValueExpression="() => ExportCodePage"
  61. ValueChanged="i=>EncodingChanged(i)">
  62. @foreach (var en in Encoding.GetEncodings()
  63. .OrderBy(p => p.Name != "utf-8")
  64. .ThenBy(p => p.Name != "gb2312")
  65. .ThenBy(p => p.Name != "shift_jis")
  66. .ThenBy(p => p.Name))
  67. {
  68. <option value="@en.CodePage">@en.Name (@en.CodePage)</option>
  69. }
  70. </InputSelect>
  71. </div>
  72. <div class="input-group mb-3">
  73. <span class="input-group-text">Extension</span>
  74. <InputText type="text" class="form-control" placeholder="Extension"
  75. Value="@ExportExtension"
  76. ValueExpression="()=>ExportExtension"
  77. ValueChanged="s=>ExportExtension=s"></InputText>
  78. </div>
  79. <div class="input-group mb-3">
  80. <span class="input-group-text">Mime</span>
  81. <InputText type="text" class="form-control" placeholder="Extension" ValueExpression="()=>ExportMime" Value="@ExportMime"></InputText>
  82. </div>
  83. </Body>
  84. <Footer>
  85. <div class="input-group">
  86. <button class="btn btn-primary" @onclick="DoExport">
  87. <i class="bi bi-save"></i>
  88. Save
  89. </button>
  90. <button class="btn btn-primary" @onclick="@DoExportAsDataUri">
  91. <i class="bi bi-gear"></i>
  92. Generate Data URI
  93. </button>
  94. @if (_exportDataUri != null)
  95. {
  96. <span class="btn btn-success">
  97. <i class="bi bi-link"></i>
  98. <a href="@_exportDataUri" download="@_exportFileName">Data URI</a>
  99. </span>
  100. }
  101. </div>
  102. </Footer>
  103. </FnzBootstrapModal>
  104. @code {
  105. public void Show(Guid playlistId)
  106. {
  107. var playlist = PlaylistHelper.PlayListLoadSave[playlistId];
  108. var uri = new Uri(NavigationManager.Uri);
  109. ExportName = $"{playlist}";
  110. ExportDomain = uri.Host;
  111. ExportDate = $"{DateTime.Now:yyMMdd}";
  112. ExportCodePage = 65001;
  113. ExportExtension = "m3u8";
  114. ExportMime = "application/mpegurl";
  115. PlaylistId = playlistId;
  116. _exportDataUri = null;
  117. StateHasChanged();
  118. mdl.Show();
  119. }
  120. private void EncodingChanged(int value)
  121. {
  122. ExportCodePage = value;
  123. ExportExtension =
  124. ExportCodePage == 65001
  125. ? "m3u8"
  126. : "m3u";
  127. StateHasChanged();
  128. }
  129. public void DoExport()
  130. {
  131. var fileName = GenerateExportFileName();
  132. var content = GenerateM3U( );
  133. JSRuntime.InvokeVoidAsync("fnz.downloadFile", fileName, ExportMime, content);
  134. mdl.Hide();
  135. }
  136. private void DoExportAsDataUri()
  137. {
  138. var outBuf = GenerateM3U( );
  139. _exportFileName = GenerateExportFileName();
  140. _exportDataUri = $"data:{ExportMime};base64," + Convert.ToBase64String(outBuf, Base64FormattingOptions.None);
  141. }
  142. private string GenerateExportFileName()
  143. {
  144. var sbFn = new StringBuilder(ExportName);
  145. if (ExportDomainCheck) sbFn.Append($"-{ExportDomain}");
  146. if (ExportDateCheck) sbFn.Append($"-{ExportDate}");
  147. sbFn.Append($".{ExportExtension}");
  148. return sbFn.ToString();
  149. }
  150. private byte[] GenerateM3U( )
  151. {
  152. var encoding = Encoding.GetEncoding(ExportCodePage);
  153. // generate m3u content
  154. var sbM3 = new StringBuilder();
  155. sbM3.WriteM3U8Header(encoding);
  156. foreach (var item in PlaylistHelper[PlaylistId])
  157. {
  158. var track = DataSet.AllTracks.FirstOrDefault(p => p.Path == item);
  159. if (track == null) continue;
  160. sbM3.AppendLine($"#EXTINF:{track.Tag?.Duration ?? 0} logo=\"{track.Disc.CoverPath.UrlEscape()}\",{track.Tag?.Artist} - {track.Tag?.Title ?? track.Name}");
  161. sbM3.AppendLine(track.Path.UrlEscape());
  162. }
  163. var outBuf = encoding.GetBytes(sbM3.ToString());
  164. return outBuf;
  165. }
  166. }