class FDroid::App

Public Class Methods

available_locales(desired_locale, localized_data) click to toggle source

Given the desired_locale, searches through the list of localized_data entries and finds those with keys which match either:

* The desired locale exactly
* The same language as the desired locale (but different region)
* Any English language (so if the desired language is not there it will suffice)

These will be sorted in order of preference:

* Exact matches (language and region)
* Language portion matches but region is absent/doesn't match.
* en-US
* en
* en-*

It is intentionally liberal in searching for either “_” or “-” to separate language and region, because they both mean (in different context) to split langugae on the left, and region on the right, and it is cheap to do so.

@param [string] desired_locale @param [Hash] localized_data @return [Array]

# File lib/fdroid/App.rb, line 213
def self.available_locales(desired_locale, localized_data)
  parts = desired_locale.split(/[_-]/)
  desired_lang = parts[0]

  locales = localized_data.keys.select do |available_locale|
    parts = available_locale.split(/[_-]/)
    available_lang = parts[0]
    available_lang == desired_lang || available_lang == 'en'
  end

  measure_locale_goodness = lambda do |locale|
    parts = locale.split(/[_-]/)
    lang = parts[0]
    region = parts.length > 1 ? parts[1] : nil
    if locale == desired_locale
      return 1
    elsif lang == desired_lang
      return 2
    elsif locale == 'en-US'
      return 3
    elsif lang == 'en' && region.nil?
      return 4
    elsif lang == 'en'
      return 5
    end
  end

  locales.sort do |a, b|
    measure_locale_goodness.call(a) <=> measure_locale_goodness.call(b)
  end
end
format_description_to_html(string) click to toggle source

Ensure newlines in descriptions are preserved (converted to “<br />” tags) Handles UNIX, Windows and MacOS newlines, with a one-to-one replacement

# File lib/fdroid/App.rb, line 147
def self.format_description_to_html(string)
  string.gsub(/(?:\n\r?|\r\n?)/, '<br />')
end
localized(available_locales, localized, field) click to toggle source

@param [string] available_locales @param [string] localized @param [string] field @return [string]

# File lib/fdroid/App.rb, line 155
def self.localized(available_locales, localized, field)
  return nil unless available_locales != nil

  available_locales.each do |l|
    if localized[l].key?(field)
      return localized[l][field]
    end
  end

  return nil
end
localized_graphic_list_paths(available_locales, localized, field) click to toggle source

Similar to localized_graphic_path, but prefixes each item in the resulting array with “chosen_locale/field/”. @see localized @see localized_graphic_path

# File lib/fdroid/App.rb, line 183
def self.localized_graphic_list_paths(available_locales, localized, field)
  return nil unless available_locales != nil
  available_locales.each do |l|
    if localized[l].key?(field)
      return localized[l][field].map { |val| "#{l}/#{field}/#{val}" }
    end
  end
  return nil
end
localized_graphic_path(available_locales, localized, field) click to toggle source

Prefixes the result with “chosen_locale/” before returning. @see localized

# File lib/fdroid/App.rb, line 169
def self.localized_graphic_path(available_locales, localized, field)
  return nil unless available_locales != nil
  available_locales.each do |l|
    if localized[l].key?(field)
      return "#{l}/#{localized[l][field]}"
    end
  end
  return nil
end
new(app, packages, locale) click to toggle source
# File lib/fdroid/App.rb, line 23
def initialize(app, packages, locale)
  # Sort packages in reverse-chronological order
  @packages = packages.map { |p| Package.new(p) }
  @app = app
  @locale = locale
  @available_locales = app.key?('localized') ? App.available_locales(locale, app['localized']) : nil
end
process_app_description(string) click to toggle source

Any transformations which are required to turn the “description” into something which is displayable via HTML is done here (e.g. replacing “fdroid.app:” schemes, formatting new lines, etc.

# File lib/fdroid/App.rb, line 129
def self.process_app_description(string)
  if string == nil
    return nil
  end

  string = self.replace_fdroid_app_links(string)
  self.format_description_to_html(string)
end

Public Instance Methods

description() click to toggle source
# File lib/fdroid/App.rb, line 58
def description
  desc = field('description') || App.localized(@available_locales, @app['localized'], 'description')

  if desc != nil
    desc = App.process_app_description(desc)
  end

  return desc
end
icon() click to toggle source
# File lib/fdroid/App.rb, line 39
def icon
  localized = App.localized_graphic_path(@available_locales, @app['localized'], 'icon')
  if localized
    "#{package_name}/#{localized}"
  elsif field('icon')
    "icons-640/#{field('icon')}"
  end
end
name() click to toggle source

this must exist since all entries are sorted by name, it uses tildes since they sort last

# File lib/fdroid/App.rb, line 50
def name
  field('name') || App.localized(@available_locales, @app['localized'], 'name') || '~missing name~'
end
package_name() click to toggle source
# File lib/fdroid/App.rb, line 31
def package_name
  field 'packageName'
end
suggested_version_code() click to toggle source
# File lib/fdroid/App.rb, line 68
def suggested_version_code
  code = field('suggestedVersionCode')
  if code != nil
    code = Integer(code)
  end
  return code
end
summary() click to toggle source
# File lib/fdroid/App.rb, line 54
def summary
  field('summary') || App.localized(@available_locales, @app['localized'], 'summary')
end
to_data() click to toggle source

Generates a hash of dumb strings to be used in templates. If a specific value is not present, then it will have a nil value. If a value can be localized, then it will choose the most appropriate translation based on @available_locales and @locale. The 'packages' key is an array of Package.to_data hashes. @return [Hash]

# File lib/fdroid/App.rb, line 82
def to_data
  {
    # These fields are taken as is from the metadata. If not present, they are
    'package_name' => package_name,
    'author_email' => field('authorEmail'),
    'author_name' => field('authorName'),
    'author_website' => field('authorWebSite'),
    'translation' => field('translation'),
    'bitcoin' => field('bitcoin'),
    'litecoin' => field('litecoin'),
    'donate' => field('donate'),
    'flattrID' => field('flattrID'),
    'liberapayID' => field('liberapayID'),
    'categories' => field('categories'),
    'anti_features' => field('antiFeatures'),
    'suggested_version_code' => suggested_version_code,
    'suggested_version_name' => @packages.detect { |p| p.version_code == suggested_version_code }&.version_name,
    'issue_tracker' => field('issueTracker'),
    'changelog' => field('changelog'),
    'license' => field('license'),
    'source_code' => field('sourceCode'),
    'website' => field('webSite'),
    'added' => field('added'),
    'last_updated' => field('lastUpdated'),
    'whats_new' => App.process_app_description(App.localized(@available_locales, @app['localized'], 'whatsNew')),

    'icon' => icon,
    'title' => name,
    'summary' => summary,

    'description' => description,
    'feature_graphic' => App.localized_graphic_path(@available_locales, @app['localized'], 'featureGraphic'),
    'phone_screenshots' => App.localized_graphic_list_paths(@available_locales, @app['localized'], 'phoneScreenshots'),
    'seven_inch_screenshots' => App.localized_graphic_list_paths(@available_locales, @app['localized'], 'sevenInchScreenshots'),
    'ten_inch_screenshots' => App.localized_graphic_list_paths(@available_locales, @app['localized'], 'tenInchScreenshots'),
    'tv_screenshots' => App.localized_graphic_list_paths(@available_locales, @app['localized'], 'tvScreenshots'),
    'wear_screenshots' => App.localized_graphic_list_paths(@available_locales, @app['localized'], 'wearScreenshots'),

    'packages' => @packages.sort.reverse.map { |p| p.to_data },

    'beautiful_url' => "/packages/#{package_name}"
  }
end
to_s() click to toggle source
# File lib/fdroid/App.rb, line 35
def to_s
  package_name
end

Private Instance Methods

field(name) click to toggle source
# File lib/fdroid/App.rb, line 247
def field(name)
  if @app.key?(name)
    value = @app[name]
    case value
    when Fixnum then return value
    when Float then return value
    when Integer then return value
    when Array then return value.map { |i| Loofah.scrub_fragment(i, :escape).to_html(:save_with => 0) }
    else
      return Loofah.scrub_fragment(value, :escape).to_html(:save_with => 0)
    end
  end
end