Welcome to mirror list, hosted at ThFree Co, Russian Federation.

downloader_adapter_ios.mm « background_downloading « storage - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c7ffb80a7d5859b514dd7a24dd990a68c8db123f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#import "storage/background_downloading/downloader_adapter_ios.h"

#import "platform/background_downloader_ios.h"

#include "storage/downloader.hpp"

#include "base/assert.hpp"
#include "base/file_name_utils.hpp"

#include <memory>
#include <utility>

@interface NSError (ToDownloaderError)

- (downloader::DownloadStatus)toDownloaderError;

@end

@implementation NSError (ToDownloaderError)

- (downloader::DownloadStatus)toDownloaderError {
  return self.code == NSURLErrorFileDoesNotExist ? downloader::DownloadStatus::FileNotFound
                                                 : downloader::DownloadStatus::Failed;
}

@end

namespace storage
{
BackgroundDownloaderAdapter::BackgroundDownloaderAdapter()
{
  m_subscriberAdapter = [[SubscriberAdapter alloc] initWithSubscribers:m_subscribers];
  BackgroundDownloader * downloader = [BackgroundDownloader sharedBackgroundMapDownloader];
  [downloader subscribe:m_subscriberAdapter];
}

void BackgroundDownloaderAdapter::Remove(CountryId const & countryId)
{
  MapFilesDownloader::Remove(countryId);
  
  if (!m_queue.Contains(countryId))
    return;

  BackgroundDownloader * downloader = [BackgroundDownloader sharedBackgroundMapDownloader];
  auto const taskIdentifier = m_queue.GetTaskInfoForCountryId(countryId);
  if (taskIdentifier)
    [downloader cancelTaskWithIdentifier:*taskIdentifier];
  m_queue.Remove(countryId);
}

void BackgroundDownloaderAdapter::Clear()
{
  MapFilesDownloader::Clear();
  
  BackgroundDownloader * downloader = [BackgroundDownloader sharedBackgroundMapDownloader];
  [downloader clear];
  m_queue.Clear();
};

QueueInterface const & BackgroundDownloaderAdapter::GetQueue() const
{
  if (m_queue.IsEmpty())
    return MapFilesDownloader::GetQueue();
    
  return m_queue;
}

void BackgroundDownloaderAdapter::Download(QueuedCountry & queuedCountry)
{
  if (!IsDownloadingAllowed())
  {
    queuedCountry.OnDownloadFinished(downloader::DownloadStatus::Failed);
    if (m_queue.IsEmpty())
    {
      for (auto const & subscriber : m_subscribers)
        subscriber->OnFinishDownloading();
    }
    return;
  }

  auto const countryId = queuedCountry.GetCountryId();
  auto const urls = MakeUrlList(queuedCountry.GetRelativeUrl());
  auto const path = queuedCountry.GetFileDownloadPath();
  
  m_queue.Append(std::move(queuedCountry));

  DownloadFromLastUrl(countryId, path, urls);
}

void BackgroundDownloaderAdapter::DownloadFromLastUrl(CountryId const & countryId,
                                                      std::string const & downloadPath,
                                                      std::vector<std::string> const & urls)
{
  if (urls.empty())
    return;

  auto onFinish = [this, countryId, downloadPath, urls = urls](NSError *error) mutable {
    downloader::DownloadStatus status = error ? [error toDownloaderError] : downloader::DownloadStatus::Completed;

    if (!m_queue.Contains(countryId))
      return;

    if (status == downloader::DownloadStatus::Failed && urls.size() > 1)
    {
      urls.pop_back();
      DownloadFromLastUrl(countryId, downloadPath, urls);
    }
    else
    {
      auto const country = m_queue.GetCountryById(countryId);
      m_queue.Remove(countryId);
      country.OnDownloadFinished(status);
    }
  };

  auto onProgress = [this, countryId](int64_t totalWritten, int64_t totalExpected) {
    if (!m_queue.Contains(countryId))
      return;

    auto const & country = m_queue.GetCountryById(countryId);
    country.OnDownloadProgress({totalWritten, totalExpected});
  };
  
  NSURL * url = [NSURL URLWithString:@(urls.back().c_str())];
  BackgroundDownloader * downloader = [BackgroundDownloader sharedBackgroundMapDownloader];
  NSUInteger taskId = [downloader downloadWithUrl:url completion:onFinish progress:onProgress];

  m_queue.SetTaskInfoForCountryId(countryId, taskId);
}

std::unique_ptr<MapFilesDownloader> GetDownloader()
{
  return std::make_unique<BackgroundDownloaderAdapter>();
}
}  // namespace storage